diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/acorn26/acorn26/vm_machdep.c mult-netbsd-3.1/sys/arch/acorn26/acorn26/vm_machdep.c --- NetBSD-3.1/sys/arch/acorn26/acorn26/vm_machdep.c 2006-10-23 19:54:45.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/acorn26/acorn26/vm_machdep.c 2007-11-11 19:41:30.000000000 +0000 @@ -169,20 +169,20 @@ } void -cpu_exit(struct lwp *l) +cpu_exit(struct inst *i, struct lwp *l) { - int s; + int s; /* * We're still running on l's stack here. This is a little * dangerous, since we're about to free it, but no-one's going - * to get a chance to reallocate it before we call - * cpu_switch(). Well, I hope they're not anyway. + * to get a chance to reallocate it before we call cpu_switch(). + * Well, I hope they're not anyway. * - * A more conventional approach would be to run on lwp0's - * stack or to have a special stack for this purpose. + * A more conventional approach would be to run on lwp0's stack + * or to have a special stack for this purpose. */ - lwp_exit2(l); + lwp_exit2(i, l); SCHED_LOCK(s); /* expected by cpu_switch */ cpu_switch(NULL, NULL); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/alpha/alpha/linux_syscall.c mult-netbsd-3.1/sys/arch/alpha/alpha/linux_syscall.c --- NetBSD-3.1/sys/arch/alpha/alpha/linux_syscall.c 2003-10-31 03:28:12.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/alpha/alpha/linux_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -97,7 +97,6 @@ #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include /* RCS ID & Copyright macro defns */ @@ -114,9 +113,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/alpha/alpha/osf1_syscall.c mult-netbsd-3.1/sys/arch/alpha/alpha/osf1_syscall.c --- NetBSD-3.1/sys/arch/alpha/alpha/osf1_syscall.c 2003-10-31 03:28:12.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/alpha/alpha/osf1_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -97,7 +97,6 @@ #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include /* RCS ID & Copyright macro defns */ @@ -114,9 +113,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/alpha/alpha/syscall.c mult-netbsd-3.1/sys/arch/alpha/alpha/syscall.c --- NetBSD-3.1/sys/arch/alpha/alpha/syscall.c 2004-07-17 05:56:32.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/alpha/alpha/syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -96,7 +96,6 @@ #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include /* RCS ID & Copyright macro defns */ @@ -112,9 +111,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/amd64/amd64/netbsd32_syscall.c mult-netbsd-3.1/sys/arch/amd64/amd64/netbsd32_syscall.c --- NetBSD-3.1/sys/arch/amd64/amd64/netbsd32_syscall.c 2004-02-13 17:07:56.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/amd64/amd64/netbsd32_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -41,7 +41,6 @@ #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -53,9 +52,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/amd64/amd64/syscall.c mult-netbsd-3.1/sys/arch/amd64/amd64/syscall.c --- NetBSD-3.1/sys/arch/amd64/amd64/syscall.c 2003-10-31 03:28:12.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/amd64/amd64/syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -41,7 +41,6 @@ #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -53,9 +52,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/arm/arm/linux_syscall.c mult-netbsd-3.1/sys/arch/arm/arm/linux_syscall.c --- NetBSD-3.1/sys/arch/arm/arm/linux_syscall.c 2004-08-01 15:19:00.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/arm/arm/linux_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -75,7 +75,6 @@ */ #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_syscall_debug.h" #include @@ -92,9 +91,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/arm/arm/syscall.c mult-netbsd-3.1/sys/arch/arm/arm/syscall.c --- NetBSD-3.1/sys/arch/arm/arm/syscall.c 2004-10-24 07:58:14.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/arm/arm/syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -77,7 +77,6 @@ */ #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_syscall_debug.h" #include @@ -95,9 +94,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/hppa/hppa/trap.c mult-netbsd-3.1/sys/arch/hppa/hppa/trap.c --- NetBSD-3.1/sys/arch/hppa/hppa/trap.c 2005-02-17 14:19:49.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/hppa/hppa/trap.c 2007-11-09 18:08:20.000000000 +0000 @@ -78,7 +78,6 @@ #include "opt_kgdb.h" #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -89,9 +88,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/conf/MULT mult-netbsd-3.1/sys/arch/i386/conf/MULT --- NetBSD-3.1/sys/arch/i386/conf/MULT 1970-01-01 01:00:00.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/i386/conf/MULT 2007-11-18 17:09:07.000000000 +0000 @@ -0,0 +1,1299 @@ +# $NetBSD: GENERIC,v 1.661.2.14 2006/07/31 12:35:22 tron Exp $ +# +# GENERIC machine description file +# +# This machine description file is used to generate the default NetBSD +# kernel. The generic kernel does not include all options, subsystems +# and device drivers, but should be useful for most applications. +# +# The machine description file can be customised for your specific +# machine to reduce the kernel size and improve its performance. +# +# For further information on compiling NetBSD kernels, see the config(8) +# man page. +# +# For further information on hardware support for this architecture, see +# the intro(4) man page. For further information about kernel options +# for this architecture, see the options(4) man page. For an explanation +# of each device driver in this file see the section 4 man page for the +# device. + +include "arch/i386/conf/std.i386" + +options INCLUDE_CONFIG_FILE # embed config file in kernel binary + +#ident "GENERIC-$Revision: 1.1 $" + +maxusers 32 # estimated number of users + +# CPU support. At least one is REQUIRED. +options I386_CPU +options I486_CPU +options I586_CPU +options I686_CPU + +# CPU-related options. +options MATH_EMULATE # floating point emulation +options VM86 # virtual 8086 emulation +options USER_LDT # user-settable LDT; used by WINE +# insert delay no-ops in interrupts; recommended on very old machines +#options PIC_DELAY + +# Enhanced SpeedStep Technology in the Pentium M +options ENHANCED_SPEEDSTEP +#options EST_FREQ_USERWRITE # any user can set frequency + +options MTRR # memory-type range register syscall support +# doesn't work with MP just yet.. +#options PERFCTRS # performance-monitoring counters support + +# delay between "rebooting ..." message and hardware reset, in milliseconds +#options CPURESET_DELAY=2000 + +# This option allows you to force a serial console at the specified +# I/O address. see console(4) for details. +#options CONSDEVNAME="\"com\"",CONADDR=0x2f8,CONSPEED=57600 +# you don't want the option below ON iff you are using the +# serial console option of the new boot strap code. +#options CONS_OVERRIDE # Always use above! independent of boot info + +# The following options override the memory sizes passed in from the boot +# block. Use them *only* if the boot block is unable to determine the correct +# values. Note that the BIOS may *correctly* report less than 640k of base +# memory if the extended BIOS data area is located at the top of base memory +# (as is the case on most recent systems). +#options REALBASEMEM=639 # size of base memory (in KB) +#options REALEXTMEM=15360 # size of extended memory (in KB) + +# Standard system options + +options INSECURE # disable kernel security levels - X needs this + +options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT +options NTP # NTP phase/frequency locked loop +#options NO_TSC_TIME # Don't use TSC microtime, even if available. + # Improves time behavior under VMware. + +options KTRACE # system call tracing via ktrace(1) +#options SYSTRACE # system call vetting via systrace(1) (byeeee) + +options SYSVMSG # System V-like message queues +options SYSVSEM # System V-like semaphores +#options SEMMNI=10 # number of semaphore identifiers +#options SEMMNS=60 # number of semaphores in system +#options SEMUME=10 # max number of undo entries per process +#options SEMMNU=30 # number of undo structures in system +options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=2048 # 2048 pages is the default +options P1003_1B_SEMAPHORE # p1003.1b semaphore support + +options LKM # loadable kernel modules + +options USERCONF # userconf(4) support +#options PIPE_SOCKETPAIR # smaller, but slower pipe(2) +options SYSCTL_INCLUDE_DESCR # Include sysctl descriptions in kernel + +# Beep when it is safe to power down the system (requires sysbeep) +#options BEEP_ONHALT +# Some tunable details of the above feature (default values used below) +#options BEEP_ONHALT_COUNT=3 # Times to beep +#options BEEP_ONHALT_PITCH=1500 # Default frequency (in Hz) +#options BEEP_ONHALT_PERIOD=250 # Default duration (in msecs) + +# Enable experimental buffer queue strategy for better responsiveness under +# high disk I/O load. Likely stable but not yet the default. +#options NEW_BUFQ_STRATEGY + +# Diagnostic/debugging support options +options DIAGNOSTIC # expensive kernel consistency checks +options DEBUG # expensive debugging checks/support +#options KMEMSTATS # kernel memory statistics (vmstat -m) +options DDB # in-kernel debugger +options DDB_ONPANIC=1 # see also sysctl(8): `ddb.onpanic' +options DDB_HISTORY_SIZE=512 # enable history editing in DDB +#options KGDB # remote debugger +#options KGDB_DEVNAME="\"com\"",KGDB_DEVADDR=0x3f8,KGDB_DEVRATE=9600 +makeoptions DEBUG="-g" # compile full symbol table + +# Compatibility options +options COMPAT_NOMID # NetBSD 0.8, 386BSD, and BSDI +options COMPAT_09 # NetBSD 0.9 +options COMPAT_10 # NetBSD 1.0 +options COMPAT_11 # NetBSD 1.1 +options COMPAT_12 # NetBSD 1.2, 386BSD, and BSDI +options COMPAT_13 # NetBSD 1.3, 386BSD, and BSDI +options COMPAT_14 # NetBSD 1.4 +options COMPAT_15 # NetBSD 1.5 +options COMPAT_16 # NetBSD 1.6 +options COMPAT_20 # NetBSD 2.0 +options COMPAT_43 # 4.3BSD, 386BSD, and BSDI +options COMPAT_386BSD_MBRPART # recognize old partition ID +#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended. + +options COMPAT_OSSAUDIO # OSS (Voxware) audio driver compatibility +options COMPAT_SVR4 # binary compatibility with SVR4 +options COMPAT_IBCS2 # binary compatibility with SCO and ISC +options COMPAT_LINUX # binary compatibility with Linux +options COMPAT_FREEBSD # binary compatibility with FreeBSD +#options COMPAT_MACH # binary compatibility with Mach binaries +#options COMPAT_DARWIN # binary compatibility with Darwin binaries +#options EXEC_MACHO # exec MACH-O binaries +#options COMPAT_PECOFF # kernel support to run Win32 apps +options COMPAT_BSDPTY # /dev/[pt]ty?? ptys. + +# File systems +file-system FFS # UFS +file-system EXT2FS # second extended file system (linux) +file-system LFS # log-structured file system +file-system MFS # memory file system +file-system NFS # Network File System client +file-system NTFS # Windows/NT file system (experimental) +file-system CD9660 # ISO 9660 + Rock Ridge file system +file-system MSDOSFS # MS-DOS file system +file-system FDESC # /dev/fd +#file-system KERNFS # /kern (removed, byeeee!) +file-system NULLFS # loopback file system +file-system OVERLAY # overlay file system +file-system PORTAL # portal filesystem (still experimental) +#file-system PROCFS # /proc (removed, byeeee!) +file-system UMAPFS # NULLFS + uid and gid remapping +file-system UNION # union file system +file-system CODA # Coda File System; also needs vcoda (below) +file-system SMBFS # experimental - CIFS; also needs nsmb (below) + +# File system options +options QUOTA # UFS quotas +#options FFS_EI # FFS Endian Independent support +options SOFTDEP # FFS soft updates support. +#options UFS_DIRHASH # UFS Large Directory Hashing - Experimental +options NFSSERVER # Network File System server +#options FFS_NO_SNAPSHOT # ffs snapshots +#options EXT2FS_SYSTEM_FLAGS # makes ext2fs file flags (append and + # immutable) behave as system flags. + +# Networking options +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +options INET6 # IPV6 +#options IPSEC # IP security +#options IPSEC_ESP # IP security (encryption part; define w/IPSEC) +#options IPSEC_NAT_T # IPsec NAT traversal (NAT-T) +#options IPSEC_DEBUG # debug for IP security +#options MROUTING # IP multicast routing +#options PIM # Protocol Independent Multicast +options NS # XNS +#options NSIP # XNS tunneling over IP +options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +options CCITT,LLC,HDLC # X.25 +options NETATALK # AppleTalk networking protocols +options PPP_BSDCOMP # BSD-Compress compression support for PPP +options PPP_DEFLATE # Deflate compression support for PPP +options PPP_FILTER # Active filter support for PPP (requires bpf) +options PFIL_HOOKS # pfil(9) packet filter hooks +options IPFILTER_LOG # ipmon(8) log support +#options IPFILTER_DEFAULT_BLOCK # block all packets by default +#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG + +#options ALTQ # Manipulate network interfaces' output queues +#options ALTQ_BLUE # Stochastic Fair Blue +#options ALTQ_CBQ # Class-Based Queueing +#options ALTQ_CDNR # Diffserv Traffic Conditioner +#options ALTQ_FIFOQ # First-In First-Out Queue +#options ALTQ_FLOWVALVE # RED/flow-valve (red-penalty-box) +#options ALTQ_HFSC # Hierarchical Fair Service Curve +#options ALTQ_LOCALQ # Local queueing discipline +#options ALTQ_PRIQ # Priority Queueing +#options ALTQ_RED # Random Early Detection +#options ALTQ_RIO # RED with IN/OUT +#options ALTQ_WFQ # Weighted Fair Queueing + +# These options control the verified exec feature +#options VERIFIED_EXEC +# +# Uncomment the fingerprint methods below that are desired. Note that +# removing fingerprint methods will have almost no impact on the kernel +# code size. +# +#options VERIFIED_EXEC_FP_RMD160 +#options VERIFIED_EXEC_FP_SHA256 +#options VERIFIED_EXEC_FP_SHA384 +#options VERIFIED_EXEC_FP_SHA512 +#options VERIFIED_EXEC_FP_SHA1 +#options VERIFIED_EXEC_FP_MD5 +# +#options VERIFIED_EXEC_DEBUG +#options VERIFIED_EXEC_DEBUG_VERBOSE + +# These options enable verbose messages for several subsystems. +# Warning, these may compile large string tables into the kernel! +#options ACPIVERBOSE # verbose ACPI device autoconfig messages +options EISAVERBOSE # verbose EISA device autoconfig messages +options MIIVERBOSE # verbose PHY autoconfig messages +options PCIVERBOSE # verbose PCI device autoconfig messages +#options PCI_CONFIG_DUMP # verbosely dump PCI config space +#options PCMCIAVERBOSE # verbose PCMCIA configuration messages +options SCSIVERBOSE # human readable SCSI error messages +options USBVERBOSE # verbose USB device autoconfig messages +#options PNPBIOSVERBOSE # verbose PnP BIOS messages +#options PNPBIOSDEBUG # more fulsome PnP BIOS debugging messages +options I2OVERBOSE # verbose I2O driver messages +options MCAVERBOSE # verbose MCA device autoconfig messages + +options NFS_BOOT_DHCP,NFS_BOOT_BOOTPARAM + +# +# wscons options +# +# builtin terminal emulations +#options WSEMUL_SUN # sun terminal emulation +options WSEMUL_VT100 # VT100 / VT220 emulation +# customization of console and kernel output - see dev/wscons/wsdisplayvar.h +options WSDISPLAY_CUSTOM_OUTPUT # color customization from wsconsctl(8) +#options WS_DEFAULT_FG=WSCOL_WHITE +#options WS_DEFAULT_BG=WSCOL_BLACK +#options WS_DEFAULT_COLATTR="(0)" +#options WS_DEFAULT_MONOATTR="(0)" +options WS_KERNEL_FG=WSCOL_GREEN +#options WS_KERNEL_BG=WSCOL_BLACK +#options WS_KERNEL_COLATTR="" +#options WS_KERNEL_MONOATTR="" +# customization of console border color +options WSDISPLAY_CUSTOM_BORDER # border customization from wsconsctl(8) +#options WSDISPLAY_BORDER_COLOR=WSCOL_BLUE # default color +# compatibility to other console drivers +options WSDISPLAY_COMPAT_PCVT # emulate some ioctls +options WSDISPLAY_COMPAT_SYSCONS # emulate some ioctls +options WSDISPLAY_COMPAT_USL # VT handling +options WSDISPLAY_COMPAT_RAWKBD # can get raw scancodes +# see dev/pckbc/wskbdmap_mfii.c for implemented layouts +#options PCKBD_LAYOUT="(KB_DE | KB_NODEAD)" +# allocate a number of virtual screens at autoconfiguration time +#options WSDISPLAY_DEFAULTSCREENS=4 +# use a large software cursor that doesn't blink +options PCDISPLAY_SOFTCURSOR +# modify the screen type of the console; defaults to "80x25" +#options VGA_CONSOLE_SCREENTYPE="\"80x24\"" +# work around a hardware bug that loaded fonts don't work; found on ATI cards +#options VGA_CONSOLE_ATI_BROKEN_FONTSEL +# the following enables some functions to get mouse console support. +# if you want a really secure system, it may be better not to enable them, +# see wsmoused(8), section SECURITY CONSIDERATIONS for more info. +#options WSDISPLAY_CHARFUNCS # mouse console support +# console scrolling support. +#options WSDISPLAY_SCROLLSUPPORT +# enable VGA raster mode capable of displaying multilingual text on console +#options VGA_RASTERCONSOLE + +# Kernel root file system and dump configuration. +config netbsd root on ? type ? +#config netbsd root on sd0a type ffs +#config netbsd root on ? type nfs + +# +# Device configuration +# + +mainbus0 at root + +cpu* at mainbus? +#ioapic* at mainbus? + +# Doesn't do anything yet. +#p64h2apic* at pci? dev? function? # P64H2 IOxAPIC + +#apm0 at mainbus0 # Advanced power management + +# Tuning for power management, see apm(4) for more details. +#options APM_NO_IDLE # Don't call BIOS CPU idle function +#options APM_V10_ONLY # Use only the APM 1.0 calls +#options APM_NO_POWEROFF # Don't power off on halt(8) +#options APM_POWER_PRINT # Print stats on the console +#options APM_DISABLE_INTERRUPTS=0 # Don't disable interrupts + + +# Basic Bus Support + +# Advanced Configuration and Power Interface + +# This option can be used to retrieve CPU and APIC information. +# that I/O APICs can be used if ACPI is enabled below. +# To use the I/O APIC(s), enable the ioapic line above. +#options MPBIOS # configure CPUs and APICs using MPBIOS +#options MPBIOS_SCANPCI # find PCI roots using MPBIOS +#options MPACPI # configure CPUs and APICs using ACPI + # (acpi at mainbus must also be enabled) +#options MPACPI_SCANPCI # find PCI roots using MPACPI + +#acpi0 at mainbus0 +#options ACPI_PCI_FIXUP # PCI interrupt routing via ACPI +#options ACPI_ACTIVATE_DEV # If set, activate inactive devices +#options ACPICA_PEDANTIC # force strict conformance to the Spec. +#options ACPI_DISABLE_ON_POWEROFF # disable acpi on power off + +# ACPI devices +#acpiacad* at acpi? # ACPI AC Adapter +#acpibat* at acpi? # ACPI Battery +#acpibut* at acpi? # ACPI Button +#acpiec* at acpi? # ACPI Embedded Controller +#acpilid* at acpi? # ACPI Lid Switch +#acpitz* at acpi? # ACPI Thermal Zone + +# Mainboard devices +#com* at acpi? # Serial communications interface +#fdc* at acpi? # Floppy disk controller +#joy* at acpi? # Joystick/Game port +#lpt* at acpi? # Parallel port +#mpu* at acpi? # Roland MPU-401 MIDI UART +#npx* at acpi? # Math coprocessor +#pckbc* at acpi? # PC keyboard controller +#wss* at acpi? # NeoMagic 256AV in wss mode + +# Sony Vaio jog dial +#spic* at acpi? # Sony Programmable I/O Controller +#wsmouse* at spic? + +# Toshiba Libretto devices +#vald* at acpi? + +# Plug-and-Play BIOS and attached devices + +#pnpbios* at mainbus? + +# mainboard audio chips +#ess* at pnpbios? index ? # ESS AudioDrive +#sb* at pnpbios? index ? # NeoMagic 256AV in sb mode +#wss* at pnpbios? index ? # NeoMagic 256AV in wss mode +#ym* at pnpbios? index ? # OPL3-SA3 + +# com port +# If enabled, consider changing "com0", "com1", and "com2" under "ISA Serial +# Interfaces" to "com*", otherwise com2 will attach at pnpbios? and there +# will be no com0. A side effect is pcmcia (and other) com? previously +# starting at com3 may attach as com1 or com2. +#com* at pnpbios? index ? # serial ports + +# parallel port +# The above "com*" comments apply, cf. "lpt0" under "ISA parallel +# "printer interfaces". +#lpt* at pnpbios? index ? # parallel ports + +#pckbc* at pnpbios? index ? # PC keyboard/mouse controller +#fdc* at pnpbios? index ? # floppy controller +#npx* at pnpbios? index ? # Math coprocessor + +# IDE controller on Toshiba Portege 3000 series (crippled PCI device) +#pciide* at pnpbios? index ? + +# PCI bus support +pci* at mainbus? bus ? +pci* at pchb? bus ? +pci* at ppb? bus ? + +# Configure PCI using BIOS information +#options PCIBIOS # PCI BIOS support +#options PCIBIOSVERBOSE # PCI BIOS verbose info +#options PCIBIOS_ADDR_FIXUP # fixup PCI I/O addresses +#options PCIBIOS_BUS_FIXUP # fixup PCI bus numbering +#options PCIBIOS_INTR_FIXUP # fixup PCI interrupt routing +#options PCIBIOS_IRQS_HINT=0x0a00 # PCI interrupts hint. IRQ 9 or 11 +#options PCIBIOS_INTR_GUESS # see pcibios(4) +#options PCIBIOS_LIBRETTO_FIXUP # this code makes the Toshiba Libretto + # L2/L3 work, but should not be enabled + # on anything else. +#options PCIBIOS_SHARP_MM20_FIXUP # this code makes the Sharp MM 20 + # work, but should not be enabled + # on anything else. +#options PCIINTR_DEBUG # super-verbose PCI interrupt fixup + +# System Controllers +elansc* at pci? dev ? function ? # AMD Elan SC520 System Controller + +# PCI bridges +#ichlpcib* at pci? dev ? function ? # Intel ICH PCI-ISA w/ watchdog and + # SpeedStep support +pchb* at pci? dev ? function ? # PCI-Host bridges +pceb* at pci? dev ? function ? # PCI-EISA bridges +pcib* at pci? dev ? function ? # PCI-ISA bridges +pcmb* at pci? dev ? function ? # PCI-MCA bridges +ppb* at pci? dev ? function ? # PCI-PCI bridges +# XXX 'puc's aren't really bridges, but there's no better place for them here +puc* at pci? dev ? function ? # PCI "universal" comm. cards + +agp* at pchb? + + +# EISA bus support +eisa0 at mainbus? +eisa0 at pceb? + +# ISA bus support +#isa0 at ichlpcib? +isa0 at mainbus? +isa0 at pceb? +isa0 at pcib? + +# PCMCIA bus support +pcmcia* at pcic? controller ? socket ? +pcmcia* at tcic? controller ? socket ? + +# MCA bus support +mca0 at mainbus? + +# ISA PCMCIA controllers +pcic0 at isa? port 0x3e0 iomem 0xd0000 iosiz 0x10000 +pcic1 at isa? port 0x3e2 iomem 0xe0000 iosiz 0x4000 +pcic2 at isa? port 0x3e4 iomem 0xe0000 iosiz 0x4000 +tcic0 at isa? port 0x240 iomem 0xd0000 iosiz 0x10000 + +# PCI PCMCIA controllers +pcic0 at pci? dev? function ? + +# ISA Plug-and-Play bus support +isapnp0 at isa? + +# ISA Plug-and-Play PCMCIA controllers +pcic* at isapnp? + +# CardBus bridge support +cbb* at pci? dev ? function ? +cardslot* at cbb? + +# CardBus bus support +cardbus* at cardslot? +pcmcia* at cardslot? + +# Coprocessor Support + +# Math Coprocessor support +npx0 at isa? port 0xf0 irq 13 # x86 math coprocessor + + +# Console Devices + +# ISA console +#pc0 at isa? port 0x60 irq 1 # pccons generic PC console driver +# Keyboard layout configuration for pccons +#options FRENCH_KBD +#options FINNISH_KBD +#options GERMAN_KBD +#options NORWEGIAN_KBD + + +# wscons +pckbc0 at isa? # pc keyboard controller +pckbd* at pckbc? # PC keyboard +pms* at pckbc? # PS/2 mouse for wsmouse +#options PMS_DISABLE_POWERHOOK # Disable PS/2 reset on resume +#options PMS_SYNAPTICS_TOUCHPAD # Enable support for Synaptics Touchpads +vga0 at isa? +vga* at pci? dev ? function ? +pcdisplay0 at isa? # CGA, MDA, EGA, HGA +#machfb* at pci? dev ? function ? # ATI Mach64 framebuffer driver +wsdisplay* at vga? console ? +wsdisplay* at pcdisplay? console ? +#wsdisplay* at machfb? console ? +wskbd* at pckbd? console ? +wsmouse* at pms? mux 0 + +pcppi0 at isa? +sysbeep0 at pcppi? + +# Serial Devices + +# PCI serial interfaces +com* at puc? port ? # 16x50s on "universal" comm boards +cy* at pci? dev ? function ? # Cyclades Cyclom-Y serial boards +cz* at pci? dev ? function ? # Cyclades-Z multi-port serial boards + +# ISA Plug-and-Play serial interfaces +com* at isapnp? # Modems and serial boards + +# PCMCIA serial interfaces +com* at pcmcia? function ? # Modems and serial cards + +pcmcom* at pcmcia? function ? # PCMCIA multi-port serial cards +com* at pcmcom? slave ? # ...and the slave devices + +# CardBus serial interfaces +#com* at cardbus? dev ? function ? # Modems and serial cards + +# ISA serial interfaces +#options COM_HAYESP # adds Hayes ESP serial board support +com0 at isa? port 0x3f8 irq 4 # Standard PC serial ports +com1 at isa? port 0x2f8 irq 3 +com2 at isa? port 0x3e8 irq 5 +#com3 at isa? port 0x2e8 irq 9 +#ast0 at isa? port 0x1a0 irq 5 # AST 4-port serial cards +#com* at ast? slave ? +#boca0 at isa? port 0x100 irq 5 # BOCA 8-port serial cards +#boca0 at isa? port 0x100 irq 5 # BOCA 16-port serial cards (BB2016) +#boca1 at isa? port 0x140 irq 5 # this line is also needed for BB2016 +#com* at boca? slave ? +#tcom0 at isa? port 0x100 irq 7 # TC-800 8-port serial cards +#com* at tcom? slave ? +#rtfps0 at isa? port 0x1230 irq 10 # RT 4-port serial cards +#com* at rtfps? slave ? +#cy0 at isa? iomem 0xd4000 irq 12 # Cyclades serial cards +#addcom0 at isa? port 0x108 irq 5 # Addonics FlexPort 8S +#com* at addcom? slave ? +#moxa0 at isa? port 0x100 irq 5 # MOXA C168H serial card (experimental) +#com* at moxa? slave ? +#ioat* at isa? port 0x220 irq 5 # BOCA IOAT66 6-port serial card +#com* at ioat? slave ? + +# MCA serial interfaces +com* at mca? slot ? # 16x50s on comm boards + +# Parallel Printer Interfaces + +# PCI parallel printer interfaces +lpt* at puc? port ? # || ports on "universal" comm boards + +# ISA parallel printer interfaces +lpt0 at isa? port 0x378 irq 7 # standard PC parallel ports +lpt1 at isa? port 0x278 +lpt2 at isa? port 0x3bc + +# Hardware monitors + +# AMD 768 and 8111 power/ACPI controllers +amdpm* at pci? dev ? function ? # RNG and SMBus 1.0 interface +#iic* at amdpm? # sensors below are on this bus +#adt7463c* at iic? addr 0x2C # Unknown other motherboard(s) +#adt7463c* at iic? addr 0x2D # Tyan S2881 +#adt7463c* at iic? addr 0x2E # Tyan S2882-D + +# LM7[89] and compatible hardware monitors +#lm0 at isa? port 0x290 # other common ports: 0x280, 0x310 + +# PC87366 hardware monitor +#nsclpcsio* at isa? + +# VIA VT82C686A hardware monitor +#viapm* at pci? dev ? function ? +#viaenv* at viapm? + + +# I2O devices +iop* at pci? dev ? function ? # I/O processor +iopsp* at iop? tid ? # SCSI/FC-AL ports +ld* at iop? tid ? # block devices +dpti* at iop? tid 0 # DPT/Adaptec control interface + + +# SCSI Controllers and Devices + +# PCI SCSI controllers +adv* at pci? dev ? function ? # AdvanSys 1200[A,B], 9xx[U,UA] SCSI +adw* at pci? dev ? function ? # AdvanSys 9x0UW[D], 3940U[2,3]W SCSI +ahc* at pci? dev ? function ? # Adaptec [23]94x, aic78x0 SCSI +ahd* at pci? dev ? function ? # Adaptec 29320, 39320 (aic790x) SCSI +bha* at pci? dev ? function ? # BusLogic 9xx SCSI +dpt* at pci? dev ? function ? # DPT SmartCache/SmartRAID +iha* at pci? dev ? function ? # Initio INIC-940/950 SCSI +isp* at pci? dev ? function ? # Qlogic ISP [12]0x0 SCSI/FibreChannel +mly* at pci? dev ? function ? # Mylex AcceleRAID and eXtremeRAID +mpt* at pci? dev ? function ? # LSI Fusion SCSI/FC +njs* at pci? dev ? function ? # Workbit NinjaSCSI-32 +pcscp* at pci? dev ? function ? # AMD 53c974 PCscsi-PCI SCSI +siop* at pci? dev ? function ? # Symbios 53c8xx SCSI +esiop* at pci? dev ? function ? # Symbios 53c875 SCSI and newer +#options SIOP_SYMLED # drive the act. LED in software +trm* at pci? dev ? function ? # Tekram DC-395U/UW/F, DC-315/U SCSI + +# EISA SCSI controllers +ahb* at eisa? slot ? # Adaptec 174[02] SCSI +ahc* at eisa? slot ? # Adaptec 274x, aic7770 SCSI +bha* at eisa? slot ? # BusLogic 7xx SCSI +dpt* at eisa? slot ? # DPT EATA SCSI +uha* at eisa? slot ? # UltraStor 24f SCSI + +# PCMCIA SCSI controllers +aic* at pcmcia? function ? # Adaptec APA-1460 SCSI +esp* at pcmcia? function ? # Qlogic ESP406/FAS408 SCSI + +# ISA Plug-and-Play SCSI controllers +aha* at isapnp? # Adaptec AHA-154[02 +aic* at isapnp? # Adaptec AHA-1520B + +# ISA SCSI controllers +adv0 at isa? port ? irq ? drq ? # AdvanSys APB-514[02] SCSI +aha0 at isa? port 0x330 irq ? drq ? # Adaptec 154[02] SCSI +aha1 at isa? port 0x334 irq ? drq ? +ahc0 at isa? port ? irq ? # Adaptec 284x SCSI +aic0 at isa? port 0x340 irq 11 # Adaptec 152[02] SCSI +bha0 at isa? port 0x330 irq ? drq ? # BusLogic [457]4X SCSI +bha1 at isa? port 0x334 irq ? drq ? +# The "nca" and "dpt" probes might give false hits or hang your machine. +#dpt0 at isa? port 0x170 irq ? drq ? # DPT SmartCache/SmartRAID +#nca0 at isa? port 0x360 irq 15 # Port-mapped NCR 53C80 controller +#nca1 at isa? iomem 0xd8000 irq 5 # Memory-mapped controller (T128, etc.) +sea0 at isa? iomem 0xc8000 irq 5 # Seagate/Future Domain SCSI +uha0 at isa? port 0x330 irq ? drq ? # UltraStor [13]4f SCSI +uha1 at isa? port 0x340 irq ? drq ? +wds0 at isa? port 0x350 irq 15 drq 6 # WD7000 and TMC-7000 controllers +wds1 at isa? port 0x358 irq 11 drq 5 + +# CardBus SCSI cards +#adv* at cardbus? dev ? function ? # AdvanSys 1200[A,B], 9xx[U,UA] SCSI +#ahc* at cardbus? dev ? function ? # Adaptec ADP-1480 +#njs* at cardbus? dev ? function ? # Workbit NinjaSCSI-32 + +# MCA SCSI cards +aha* at mca? slot ? # Adaptec AHA-1640 + +# SCSI bus support +scsibus* at scsi? + +# SCSI devices +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI autochangers +ses* at scsibus? target ? lun ? # SCSI Enclosure Services devices +ss* at scsibus? target ? lun ? # SCSI scanners +uk* at scsibus? target ? lun ? # SCSI unknown + + +# RAID controllers and devices +aac* at pci? dev ? function ? # Adaptec AAC family +amr* at pci? dev ? function ? # AMI/LSI Logic MegaRAID +cac* at eisa? slot ? # Compaq EISA array controllers +cac* at pci? dev ? function ? # Compaq PCI array controllers +ciss* at pci? dev ? function ? # HP Smart Array controllers +icp* at pci? dev ? function ? # ICP-Vortex GDT & Intel RAID +mlx* at pci? dev ? function ? # Mylex DAC960 & DEC SWXCR family +mlx* at eisa? slot ? # Mylex DAC960 & DEC SWXCR family +twe* at pci? dev ? function ? # 3ware Escalade RAID controllers +twa* at pci? dev ? function ? # 3ware Escalade 9xxx RAID controllers + +ld* at aac? unit ? # logical disk devices +ld* at amr? unit ? +ld* at cac? unit ? +ld* at icp? unit ? +ld* at twe? unit ? +ld* at twa? unit ? +ld* at mlx? unit ? + +icpsp* at icp? unit ? # SCSI pass-through + +# IDE and related devices +# PCI IDE controllers - see pciide(4) for supported hardware. +# The 0x0001 flag force the driver to use DMA, even if the driver doesn't know +# how to set up DMA modes for this chip. This may work, or may cause +# a machine hang with some controllers. +pciide* at pci? dev ? function ? flags 0x0000 # GENERIC pciide driver +acardide* at pci? dev ? function ? # Acard IDE controllers +aceride* at pci? dev ? function ? # Acer Lab IDE controllers +artsata* at pci? dev ? function ? # Intel i31244 SATA controller +cmdide* at pci? dev ? function ? # CMD tech IDE controllers +cypide* at pci? dev ? function ? # Cypress IDE controllers +geodeide* at pci? dev ? function ? # AMD Geode IDE controllers +hptide* at pci? dev ? function ? # Triones/HighPoint IDE controllers +iteide* at pci? dev ? function ? # IT Express IDE controllers +ixpide* at pci? dev ? function ? # ATI IXP IDE controllers +optiide* at pci? dev ? function ? # Opti IDE controllers +piixide* at pci? dev ? function ? # Intel IDE controllers +pdcide* at pci? dev ? function ? # Promise IDE controllers +pdcsata* at pci? dev ? function ? # Promise SATA150 controllers +rccide* at pci? dev ? function ? # ServerWorks IDE controllers +satalink* at pci? dev ? function ? # SiI SATALink controllers +siside* at pci? dev ? function ? # SiS IDE controllers +slide* at pci? dev ? function ? # Symphony Labs IDE controllers +svwsata* at pci? dev ? function ? # ServerWorks SATA controllers +stpcide* at pci? dev ? function ? # STMicro STPC IDE controllers +viaide* at pci? dev ? function ? # VIA/AMD/Nvidia IDE controllers + +# ISA Plug-and-Play IDE controllers +wdc* at isapnp? + +# PCMCIA IDE controllers +wdc* at pcmcia? function ? + +# ISA ST506, ESDI, and IDE controllers +# Use flags 0x01 if you want to try to use 32bits data I/O (the driver will +# fall back to 16bits I/O if 32bits I/O are not functional). +# Some controllers pass the initial 32bit test, but will fail later. +wdc0 at isa? port 0x1f0 irq 14 flags 0x00 +wdc1 at isa? port 0x170 irq 15 flags 0x00 + +# ATA (IDE) bus support +atabus* at ata? + +# IDE drives +# Flags are used only with controllers that support DMA operations +# and mode settings (e.g. some pciide controllers) +# The lowest order four bits (rightmost digit) of the flags define the PIO +# mode to use, the next set of four bits the DMA mode and the third set the +# UltraDMA mode. For each set of four bits, the 3 lower bits define the mode +# to use, and the last bit must be 1 for this setting to be used. +# For DMA and UDMA, 0xf (1111) means 'disable'. +# 0x0fac means 'use PIO mode 4, DMA mode 2, disable UltraDMA'. +# (0xc=1100, 0xa=1010, 0xf=1111) +# 0x0000 means "use whatever the drive claims to support". +wd* at atabus? drive ? flags 0x0000 + +# ATA RAID configuration support, as found on some Promise controllers. +pseudo-device ataraid +ld* at ataraid? vendtype ? unit ? + +# ATAPI bus support +atapibus* at atapi? + +# ATAPI devices +# flags have the same meaning as for IDE drives. +cd* at atapibus? drive ? flags 0x0000 # ATAPI CD-ROM drives +sd* at atapibus? drive ? flags 0x0000 # ATAPI disk drives +st* at atapibus? drive ? flags 0x0000 # ATAPI tape drives +uk* at atapibus? drive ? flags 0x0000 # ATAPI unknown + + +# Miscellaneous mass storage devices + +# ISA floppy +fdc0 at isa? port 0x3f0 irq 6 drq 2 # standard PC floppy controllers +#fdc1 at isa? port 0x370 irq ? drq ? +fd* at fdc? drive ? # the drives themselves +# some machines need you to do this instead of fd* +#fd0 at fdc0 drive 0 + +# ISA CD-ROM devices +#mcd0 at isa? port 0x300 irq 10 # Mitsumi CD-ROM drives + +# ISA tape devices +# note: the wt driver conflicts unpleasantly with SMC boards at the +# same I/O address. The probe reprograms their EEPROMs. Don't +# uncomment it unless you are actually using it. +#wt0 at isa? port 0x308 irq 5 drq 1 # Archive and Wangtek QIC tape drives + +# MCA ESDI devices +edc* at mca? slot ? # IBM ESDI Disk Controllers +ed* at edc? + + +# Network Interfaces + +# PCI network interfaces +an* at pci? dev ? function ? # Aironet PC4500/PC4800 (802.11) +#ath* at pci? dev ? function ? # Atheros 5210/5211/5212 802.11 +atw* at pci? dev ? function ? # ADMtek ADM8211 (802.11) +bce* at pci? dev ? function ? # Broadcom 4401 10/100 Ethernet +bge* at pci? dev ? function ? # Broadcom 570x gigabit Ethernet +dge* at pci? dev ? function ? # Intel 82597 10GbE LR +en* at pci? dev ? function ? # ENI/Adaptec ATM +ep* at pci? dev ? function ? # 3Com 3c59x +epic* at pci? dev ? function ? # SMC EPIC/100 Ethernet +esh* at pci? dev ? function ? # Essential HIPPI card +ex* at pci? dev ? function ? # 3Com 90x[BC] +fpa* at pci? dev ? function ? # DEC DEFPA FDDI +fxp* at pci? dev ? function ? # Intel EtherExpress PRO 10+/100B +ipw* at pci? dev ? function ? # Intel PRO/Wireless 2100 +iwi* at pci? dev ? function ? # Intel PRO/Wireless 2200BG +gsip* at pci? dev ? function ? # NS83820 Gigabit Ethernet +hme* at pci? dev ? function ? # Sun Microelectronics STP2002-STQ +le* at pci? dev ? function ? # PCnet-PCI Ethernet +lmc* at pci? dev ? function ? # Lan Media Corp SSI/HSSI/DS3 +mtd* at pci? dev ? function ? # Myson MTD803 3-in-1 Ethernet +ne* at pci? dev ? function ? # NE2000-compatible Ethernet +nfe* at pci? dev ? function ? # NVIDIA nForce Ethernet +ntwoc* at pci? dev ? function ? # Riscom/N2 PCI Sync Serial +pcn* at pci? dev ? function ? # AMD PCnet-PCI Ethernet +re* at pci? dev ? function ? # Realtek 8139C+/8169/8169S/8110S +rtk* at pci? dev ? function ? # Realtek 8129/8139 +sf* at pci? dev ? function ? # Adaptec AIC-6915 Ethernet +sip* at pci? dev ? function ? # SiS 900/DP83815 Ethernet +skc* at pci? dev ? function ? # SysKonnect SK9821 Gigabit Ethernet +sk* at skc? # SysKonnect SK9821 Gigabit Ethernet +ste* at pci? dev ? function ? # Sundance ST-201 Ethernet +stge* at pci? dev ? function ? # Sundance/Tamarack TC9021 Gigabit +ti* at pci? dev ? function ? # Alteon ACEnic gigabit Ethernet +tl* at pci? dev ? function ? # ThunderLAN-based Ethernet +tlp* at pci? dev ? function ? # DECchip 21x4x and clones +txp* at pci? dev ? function ? # 3com 3cr990 +vge* at pci? dev ? function ? # VIATech VT612X Gigabit Ethernet +vr* at pci? dev ? function ? # VIA Rhine Fast Ethernet +wi* at pci? dev ? function ? # Intersil Prism Mini-PCI (802.11b) +wm* at pci? dev ? function ? # Intel 8254x gigabit +xge* at pci? dev ? function ? # Neterion (S2io) Xframe-I 10GbE + +# EISA network interfaces +ep* at eisa? slot ? # 3Com 3c579 Ethernet +fea* at eisa? slot ? # DEC DEFEA FDDI +tlp* at eisa? slot ? # DEC DE-425 Ethernet + +# ISA Plug-and-Play network interfaces +an* at isapnp? # Aironet 802.11 +ep* at isapnp? # 3Com 3c509 Ethernet +fmv* at isapnp? # Fujitsu FMV-183 +le* at isapnp? # AMD PCnet-ISA Ethernet +ne* at isapnp? # NE2000-compatible Ethernet +tr* at isapnp? # IBM/3COM TROPIC Token-Ring + +# PCMCIA network interfaces +an* at pcmcia? function ? # Aironet PC4500/PC4800 (802.11) +awi* at pcmcia? function ? # BayStack 650/660 (802.11FH/DS) +cnw* at pcmcia? function ? # Xircom/Netwave AirSurfer +cs* at pcmcia? function ? # CS89xx Ethernet +ep* at pcmcia? function ? # 3Com 3c589 and 3c562 Ethernet +mbe* at pcmcia? function ? # MB8696x based Ethernet +ne* at pcmcia? function ? # NE2000-compatible Ethernet +ray* at pcmcia? function ? # Raytheon Raylink (802.11) +sm* at pcmcia? function ? # Megahertz Ethernet +# tr at pcmcia has problems with Cardbus bridges +#tr* at pcmcia? function ? # TROPIC based Token-Ring +wi* at pcmcia? function ? # Lucent/Intersil WaveLan IEEE (802.11) +xirc* at pcmcia? function ? # Xircom CreditCard Ethernet +com* at xirc? +xi* at xirc? +mhzc* at pcmcia? function ? # Megahertz Ethernet/Modem combo cards +com* at mhzc? +sm* at mhzc? + +# ISA network interfaces +ate0 at isa? port 0x2a0 irq ? # AT1700 +cs0 at isa? port 0x300 iomem ? irq ? drq ? # CS8900 Ethernet +ec0 at isa? port 0x250 iomem 0xd8000 irq 9 # 3Com 3c503 Ethernet +eg0 at isa? port 0x280 irq 9 # 3C505 ethernet cards +el0 at isa? port 0x300 irq 9 # 3C501 ethernet cards +ep* at isa? port ? irq ? # 3C509 ethernet cards +ef0 at isa? port 0x360 iomem 0xd0000 irq 7 # 3C507 +ai0 at isa? port 0x360 iomem 0xd0000 irq 7 # StarLAN +fmv0 at isa? port 0x2a0 irq ? # FMV-181/182 +ix0 at isa? port 0x300 irq 10 # EtherExpress/16 +iy0 at isa? port 0x360 irq ? # EtherExpress PRO 10 ISA +lc0 at isa? port 0x320 iomem ? irq ? # DEC EtherWORKS III (LEMAC) +#depca0 at isa? port 0x300 iomem 0xc8000 iosiz 0x8000 irq 5 # DEPCA +#le* at depca? +nele0 at isa? port 0x320 irq 9 drq 7 # NE2100 +le* at nele? +#ntwoc0 at isa? port 0x300 irq 5 iomem 0xc8000 flags 1 # Riscom/N2 sync serial +bicc0 at isa? port 0x320 irq 10 drq 7 # BICC IsoLan +le* at bicc? +ne0 at isa? port 0x280 irq 9 # NE[12]000 ethernet cards +ne1 at isa? port 0x300 irq 10 +sm0 at isa? port 0x300 irq 10 # SMC91C9x Ethernet +tr0 at isa? port 0xa20 iomem 0xd8000 irq ? # IBM TROPIC based Token-Ring +tr1 at isa? port 0xa24 iomem 0xd0000 irq ? # IBM TROPIC based Token-Ring +tr* at isa? port ? irq ? # 3COM TROPIC based Token-Ring +we0 at isa? port 0x280 iomem 0xd0000 irq 9 # WD/SMC Ethernet +we1 at isa? port 0x300 iomem 0xcc000 irq 10 + +# CardBus network cards +#ath* at cardbus? dev ? function ? # Atheros 5210/5211/5212 802.11 +#atw* at cardbus? dev ? function ? # ADMtek ADM8211 (802.11) +#ex* at cardbus? dev ? function ? # 3Com 3C575TX +#fxp* at cardbus? dev ? function ? # Intel i8255x +#rtk* at cardbus? dev ? function ? # Realtek 8129/8139 +#tlp* at cardbus? dev ? function ? # DECchip 21143 + +# MCA network cards +elmc* at mca? slot ? # 3Com EtherLink/MC (3c523) +ep* at mca? slot ? # 3Com EtherLink III (3c529) +we* at mca? slot ? # WD/SMC Ethernet +ate* at mca? slot ? # Allied Telesis AT1720 +ne* at mca? slot ? # Novell NE/2 and clones +tr* at mca? slot ? # IBM Token Ring adapter +le* at mca? slot ? # SKNET Personal/MC2+ + +# MII/PHY support +acphy* at mii? phy ? # Altima AC101 and AMD Am79c874 PHYs +amhphy* at mii? phy ? # AMD 79c901 Ethernet PHYs +bmtphy* at mii? phy ? # Broadcom BCM5201 and BCM5202 PHYs +brgphy* at mii? phy ? # Broadcom BCM5400-family PHYs +ciphy* at mii? phy ? # Cicada CS8201 Gig-E PHYs +dmphy* at mii? phy ? # Davicom DM9101 PHYs +exphy* at mii? phy ? # 3Com internal PHYs +gentbi* at mii? phy ? # Generic Ten-Bit 1000BASE-[CLS]X PHYs +glxtphy* at mii? phy ? # Level One LXT-1000 PHYs +gphyter* at mii? phy ? # NS83861 Gig-E PHY +icsphy* at mii? phy ? # Integrated Circuit Systems ICS189x +igphy* at mii? phy ? # Intel IGP01E1000 +inphy* at mii? phy ? # Intel 82555 PHYs +iophy* at mii? phy ? # Intel 82553 PHYs +lxtphy* at mii? phy ? # Level One LXT-970 PHYs +makphy* at mii? phy ? # Marvell Semiconductor 88E1000 PHYs +nsphy* at mii? phy ? # NS83840 PHYs +nsphyter* at mii? phy ? # NS83843 PHYs +pnaphy* at mii? phy ? # generic HomePNA PHYs +qsphy* at mii? phy ? # Quality Semiconductor QS6612 PHYs +sqphy* at mii? phy ? # Seeq 80220/80221/80223 PHYs +tlphy* at mii? phy ? # ThunderLAN PHYs +tqphy* at mii? phy ? # TDK Semiconductor PHYs +ukphy* at mii? phy ? # generic unknown PHYs +urlphy* at mii? phy ? # Realtek RTL8150L internal PHYs + + +# USB Controller and Devices + +# PCI USB controllers +ehci* at pci? dev ? function ? # Enhanced Host Controller +ohci* at pci? dev ? function ? # Open Host Controller +uhci* at pci? dev ? function ? # Universal Host Controller (Intel) + +# CardBus USB controllers +#ehci* at cardbus? dev ? function ? # Enhanced Host Controller +#ohci* at cardbus? dev ? function ? # Open Host Controller + +# ISA USB controllers +#slhci0 at isa? port 0x300 irq 5 # ScanLogic SL811HS + +# USB bus support +usb* at ehci? +usb* at ohci? +usb* at uhci? +#usb* at slhci? + +# USB Hubs +uhub* at usb? +uhub* at uhub? port ? configuration ? interface ? + +# USB HID device +uhidev* at uhub? port ? configuration ? interface ? + +# USB Mice +ums* at uhidev? reportid ? +wsmouse* at ums? mux 0 + +# USB eGalax touch-panel +uep* at uhub? port ? +wsmouse* at uep? mux 0 + +# USB Keyboards +ukbd* at uhidev? reportid ? +wskbd* at ukbd? console ? mux 1 + +# USB Generic HID devices +uhid* at uhidev? reportid ? + +# USB Printer +ulpt* at uhub? port ? configuration ? interface ? + +# USB Modem +umodem* at uhub? port ? configuration ? +ucom* at umodem? + +# USB Mass Storage +umass* at uhub? port ? configuration ? interface ? +scsibus* at umass? +wd* at umass? + +# USB audio +uaudio* at uhub? port ? configuration ? + +# USB MIDI +umidi* at uhub? port ? configuration ? + +# USB IrDA +# USB-IrDA bridge spec +uirda* at uhub? port ? configuration ? interface ? +irframe* at uirda? + +# SigmaTel STIr4200 USB/IrDA Bridge +ustir* at uhub? port ? +irframe* at ustir? + +# USB Ethernet adapters +aue* at uhub? port ? # ADMtek AN986 Pegasus based adapters +axe* at uhub? port ? # ASIX AX88172 based adapters +cdce* at uhub? port ? # CDC, Ethernet Networking Control Model +cue* at uhub? port ? # CATC USB-EL1201A based adapters +kue* at uhub? port ? # Kawasaki LSI KL5KUSB101B based adapters +udav* at uhub? port ? # Davicom DM9601 based adapters +url* at uhub? port ? # Realtek RTL8150L based adapters + +# USB 802.11b adapters +atu* at uhub? port ? # Atmel AT76C50XX based adapters + +# Prolific PL2301/PL2302 host-to-host adapter +upl* at uhub? port ? + +# Serial adapters +ubsa* at uhub? port ? # Belkin serial adapter +ucom* at ubsa? portno ? + +uftdi* at uhub? port ? # FTDI FT8U100AX serial adapter +ucom* at uftdi? portno ? + +umct* at uhub? port ? # MCT USB-RS232 serial adapter +ucom* at umct? portno ? + +uplcom* at uhub? port ? # I/O DATA USB-RSAQ2 serial adapter +ucom* at uplcom? portno ? + +uvscom* at uhub? port ? # SUNTAC Slipper U VS-10U serial adapter +ucom* at uvscom? portno ? + +# Diamond Multimedia Rio 500 +urio* at uhub? port ? + +# USB Handspring Visor +uvisor* at uhub? port ? +ucom* at uvisor? + +# Kyocera AIR-EDGE PHONE +ukyopon* at uhub? port ? +ucom* at ukyopon? portno ? + +# USB scanners +uscanner* at uhub? port ? + +# USB scanners that use SCSI emulation, e.g., HP5300 +usscanner* at uhub? port ? + +# Y@P firmware loader +uyap* at uhub? port ? + +# D-Link DSB-R100 USB radio +udsbr* at uhub? port ? +radio* at udsbr? + +# USB Generic driver +ugen* at uhub? port ? + + +# IrDA and Consumer Ir devices + +# Toshiba Oboe +oboe* at pci? dev ? function ? +irframe* at oboe? + +# PCI IEEE1394 controllers +#fwohci* at pci? dev ? function ? # IEEE1394 Open Host Controller + +# CardBus IEEE1394 controllers +#fwohci* at cardbus? dev ? function ? # IEEE1394 Open Host Controller + +#fw* at fwbus? # IP over 1394 + +# IEEE1394 nodes +#fwnode* at fwbus? idhi ? idlo ? +#sbpscsi* at fwnode? +#scsibus* at sbpscsi? + +# Audio Devices + +# PCI audio devices +auacer* at pci? dev ? function ? # ALi M5455 integrated AC'97 Audio +auich* at pci? dev ? function ? # Intel ICH integrated AC'97 Audio +auixp* at pci? dev ? function ? # ATI IXP AC'97 Audio +autri* at pci? dev ? function ? # Trident 4DWAVE based AC'97 Audio +auvia* at pci? dev ? function ? # VIA VT82C686A integrated AC'97 Audio +azalia* at pci? dev ? function ? # High Definition Audio +clcs* at pci? dev ? function ? # Cirrus Logic CS4280 +clct* at pci? dev ? function ? # Cirrus Logic CS4281 +cmpci* at pci? dev ? function ? # C-Media CMI8338/8738 +eap* at pci? dev ? function ? # Ensoniq AudioPCI +emuxki* at pci? dev ? function ? # Creative SBLive! and PCI512 +esa* at pci? dev ? function ? # ESS Allegro-1 / Maestro-3 PCI Audio +esm* at pci? dev ? function ? # ESS Maestro-1/2/2e PCI Audio Accelerator +eso* at pci? dev ? function ? # ESS Solo-1 PCI AudioDrive +fms* at pci? dev ? function ? # Forte Media FM801 +neo* at pci? dev ? function ? # NeoMagic 256 AC'97 Audio +sv* at pci? dev ? function ? # S3 SonicVibes +yds* at pci? dev ? function ? # Yamaha DS-1 PCI Audio + +# ISA Plug-and-Play audio devices +ess* at isapnp? # ESS Tech ES1887, ES1888, ES888 audio +guspnp* at isapnp? # Gravis Ultra Sound PnP audio +sb* at isapnp? # SoundBlaster-compatible audio +wss* at isapnp? # Windows Sound System +ym* at isapnp? # Yamaha OPL3-SA3 audio + +# ISA audio devices +# the "aria" probe might give false hits +#aria0 at isa? port 0x290 irq 10 # Aria +#ess0 at isa? port 0x220 irq 5 drq 1 drq2 5 # ESS 18XX +gus0 at isa? port 0x220 irq 7 drq 1 drq2 6 # Gravis Ultra Sound +pas0 at isa? port 0x220 irq 7 drq 1 # ProAudio Spectrum +#pss0 at isa? port 0x220 irq 7 drq 6 # Personal Sound System +#sp0 at pss0 port 0x530 irq 10 drq 0 # sound port driver +sb0 at isa? port 0x220 irq 5 drq 1 drq2 5 # SoundBlaster +wss0 at isa? port 0x530 irq 10 drq 0 drq2 1 # Windows Sound System + +# PCMCIA audio devices +#esl* at pcmcia? function ? # ESS 1688 AudioDrive + +#cms0 at isa? port 0x220 # Creative Music System + +# OPL[23] FM synthesizers +#opl0 at isa? port 0x388 # use only if not attached to sound card +opl* at cmpci? flags 1 +#opl* at esl? +opl* at eso? +opl* at ess? +opl* at fms? +opl* at sb? +opl* at sv? +opl* at wss? +opl* at yds? +opl* at ym? + +# Audio support +audio* at audiobus? + +# MPU 401 UARTs +#mpu* at isa? port 0x330 irq 9 # MPU401 or compatible card +mpu* at cmpci? +mpu* at eso? +mpu* at fms? +mpu* at sb? +mpu* at yds? +mpu* at ym? + +# MIDI support +midi* at midibus? +midi* at pcppi? # MIDI interface to the PC speaker + +# The spkr driver provides a simple tone interface to the built in speaker. +#spkr0 at pcppi? # PC speaker + + +# FM-Radio devices +# ISA radio devices +#az0 at isa? port 0x350 # Aztech/PackardBell FM Radio Card +#az1 at isa? port 0x358 +#rt0 at isa? port 0x20c # AIMS Lab Radiotrack & compatible +#rt1 at isa? port 0x284 +#rt2 at isa? port 0x30c +#rt3 at isa? port 0x384 +#rtii0 at isa? port 0x20c # AIMS Lab Radiotrack II FM Radio Card +#rtii1 at isa? port 0x30c +#sf2r0 at isa? port 0x384 # SoundForte RadioLink SF16-FMR2 FM Radio Card + +# PCI radio devices +#gtp* at pci? dev ? function ? # Guillemot Maxi Radio FM 2000 Radio Card + +# Radio support +#radio* at az? +#radio* at gtp? +#radio* at rt? +#radio* at rtii? +#radio* at sf2r? + + +# TV cards + +# Brooktree 848/849/878/879 based TV cards +bktr* at pci? dev ? function ? +radio* at bktr? + + +# Mice + +# ISA busmice +lms0 at isa? port 0x23c irq 5 # Logitech bus mouse +lms1 at isa? port 0x238 irq 5 +mms0 at isa? port 0x23c irq 5 # Microsoft InPort mouse +mms1 at isa? port 0x238 irq 5 +wsmouse* at lms? mux 0 +wsmouse* at mms? mux 0 + + +# Cryptographic Devices + +# PCI cryptographic devices +hifn* at pci? dev ? function ? # Hifn 7755/7811/795x +ubsec* at pci? dev ? function ? # Broadcom 5501/5601/580x/582x + + +# Joysticks + +#joy* at pnpbios? index ? # Game port + +# ISA Plug-and-Play joysticks +joy* at isapnp? # Game ports (usually on audio cards) + +# PCI joysticks +joy* at pci? # Game ports (usually on audio cards) +joy* at eso? # ESS Solo-1 on-board joystick + +# ISA joysticks. Probe is a little strange; add only if you have one. +#joy0 at isa? port 0x201 + + +# Miscellaneous Devices + +geodewdog* at pci? dev ? function ? # AMD Geode SC1100 watchdog timer + +# Planetconnect Satellite receiver driver. +#satlink0 at isa? port 0x300 drq 1 + +# Middle Digital, Inc. PCI-Weasel serial console board control +# devices (watchdog timer, etc.) +weasel* at pci? + +# Pull in optional local configuration +include "arch/i386/conf/GENERIC.local" + + +# Pseudo-Devices + +pseudo-device crypto # opencrypto framework + +# disk/mass storage pseudo-devices +pseudo-device ccd 4 # concatenated/striped disk devices +#pseudo-device cgd 4 # cryptographic disk devices +pseudo-device raid 8 # RAIDframe disk driver +options RAID_AUTOCONFIG # auto-configuration of RAID components +# Options to enable various other RAIDframe RAID types. +#options RF_INCLUDE_EVENODD=1 +#options RF_INCLUDE_RAID5_RS=1 +#options RF_INCLUDE_PARITYLOGGING=1 +#options RF_INCLUDE_CHAINDECLUSTER=1 +#options RF_INCLUDE_INTERDECLUSTER=1 +#options RF_INCLUDE_PARITY_DECLUSTERING=1 +#options RF_INCLUDE_PARITY_DECLUSTERING_DS=1 +pseudo-device fss 4 # file system snapshot device + +# Vinum +# pseudo-device vinum 8 # Vinum +# options VINUMDEBUG + +pseudo-device md 1 # memory disk device (ramdisk) +pseudo-device vnd 4 # disk-like interface to files +options VND_COMPRESSION # compressed vnd(4) + +# network pseudo-devices +pseudo-device bpfilter 8 # Berkeley packet filter +pseudo-device ipfilter # IP filter (firewall) and NAT +pseudo-device loop # network loopback +pseudo-device ppp 2 # Point-to-Point Protocol +pseudo-device pppoe # PPP over Ethernet (RFC 2516) +pseudo-device sl 2 # Serial Line IP +pseudo-device strip 2 # Starmode Radio IP (Metricom) +pseudo-device irframetty # IrDA frame line discipline +pseudo-device tap # virtual Ethernet +pseudo-device tun 2 # network tunneling over tty +pseudo-device gre 2 # generic L3 over IP tunnel +pseudo-device gif 4 # IPv[46] over IPv[46] tunnel (RFC1933) +#pseudo-device faith 1 # IPv[46] tcp relay translation i/f +#pseudo-device stf 1 # 6to4 IPv6 over IPv4 encapsulation +pseudo-device vlan # IEEE 802.1q encapsulation +pseudo-device bridge # simple inter-network bridging +#options BRIDGE_IPF # bridge uses IP/IPv6 pfil hooks too +#pseudo-device pf # PF packet filter +#pseudo-device pflog # PF log if + +# miscellaneous pseudo-devices +pseudo-device pty # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device sequencer 1 # MIDI sequencer +# rnd works; RND_COM does not on port i386 yet. +pseudo-device rnd # /dev/random and in-kernel generator +#options RND_COM # use "com" randomness as well (BROKEN) +pseudo-device clockctl # user control of clock subsystem + +# a pseudo device needed for Coda # also needs CODA (above) +pseudo-device vcoda 4 # coda minicache <-> venus comm. + +# a pseudo device needed for SMBFS +pseudo-device nsmb # experimental - SMB requester + +# a pseudo device needed for verified exec +#pseudo-device veriexec 1 + +# wscons pseudo-devices +pseudo-device wsmux # mouse & keyboard multiplexor +pseudo-device wsfont +pseudo-device ksyms # /dev/ksyms diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/db_trace.c mult-netbsd-3.1/sys/arch/i386/i386/db_trace.c --- NetBSD-3.1/sys/arch/i386/i386/db_trace.c 2004-02-28 20:30:58.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/db_trace.c 2007-11-10 19:27:10.000000000 +0000 @@ -395,7 +395,8 @@ struct user *u; struct lwp *l; (*pr)("trace: pid %d ", (int)addr); - p = pfind(addr); + /* FIXME - instances */ + p = pfind(NULL, addr); if (p == NULL) { (*pr)("not found\n"); return; diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/freebsd_syscall.c mult-netbsd-3.1/sys/arch/i386/i386/freebsd_syscall.c --- NetBSD-3.1/sys/arch/i386/i386/freebsd_syscall.c 2004-02-13 18:57:19.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/freebsd_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -42,7 +42,6 @@ #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include @@ -54,9 +53,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/ibcs2_syscall.c mult-netbsd-3.1/sys/arch/i386/i386/ibcs2_syscall.c --- NetBSD-3.1/sys/arch/i386/i386/ibcs2_syscall.c 2004-02-13 18:57:19.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/ibcs2_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -43,7 +43,6 @@ #include "opt_syscall_debug.h" #include "opt_vm86.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include @@ -55,9 +54,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/linux_syscall.c mult-netbsd-3.1/sys/arch/i386/i386/linux_syscall.c --- NetBSD-3.1/sys/arch/i386/i386/linux_syscall.c 2004-02-13 18:57:19.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/linux_syscall.c 2007-11-09 18:08:20.000000000 +0000 @@ -43,7 +43,6 @@ #include "opt_syscall_debug.h" #include "opt_vm86.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include @@ -55,9 +54,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/mach_machdep.c mult-netbsd-3.1/sys/arch/i386/i386/mach_machdep.c --- NetBSD-3.1/sys/arch/i386/i386/mach_machdep.c 2004-02-13 11:36:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/mach_machdep.c 2007-11-18 14:10:50.000000000 +0000 @@ -170,6 +170,7 @@ * Copy right from parent. Will disaprear * the day we will have struct lwp. */ + KASSERT(p->p_pptr); mach_copy_right(p->p_pptr, p); tf = trapframe(p); diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/mach_syscall.c mult-netbsd-3.1/sys/arch/i386/i386/mach_syscall.c --- NetBSD-3.1/sys/arch/i386/i386/mach_syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/mach_syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -42,7 +42,6 @@ #include "opt_syscall_debug.h" #include "opt_vm86.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -53,9 +52,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/svr4_syscall.c mult-netbsd-3.1/sys/arch/i386/i386/svr4_syscall.c --- NetBSD-3.1/sys/arch/i386/i386/svr4_syscall.c 2004-02-13 18:57:19.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/i386/i386/svr4_syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -43,7 +43,6 @@ #include "opt_syscall_debug.h" #include "opt_vm86.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #endif #include @@ -55,9 +54,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/syscall.c mult-netbsd-3.1/sys/arch/i386/i386/syscall.c --- NetBSD-3.1/sys/arch/i386/i386/syscall.c 2004-09-30 22:32:27.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/i386/i386/syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -42,7 +42,6 @@ #include "opt_syscall_debug.h" #include "opt_vm86.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -53,9 +52,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/i386/i386/trap.c mult-netbsd-3.1/sys/arch/i386/i386/trap.c --- NetBSD-3.1/sys/arch/i386/i386/trap.c 2005-10-11 22:04:19.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/i386/i386/trap.c 2007-11-12 16:59:26.000000000 +0000 @@ -101,6 +101,7 @@ #include #include #include +#include #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/m68k/m68k/linux_syscall.c mult-netbsd-3.1/sys/arch/m68k/m68k/linux_syscall.c --- NetBSD-3.1/sys/arch/m68k/m68k/linux_syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/m68k/m68k/linux_syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -115,7 +115,6 @@ #include "opt_syscall_debug.h" #include "opt_execfmt.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -128,9 +127,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/m68k/m68k/m68k_syscall.c mult-netbsd-3.1/sys/arch/m68k/m68k/m68k_syscall.c --- NetBSD-3.1/sys/arch/m68k/m68k/m68k_syscall.c 2004-08-28 23:06:28.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/m68k/m68k/m68k_syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -115,7 +115,6 @@ #include "opt_syscall_debug.h" #include "opt_execfmt.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_compat_netbsd.h" #include "opt_compat_aout_m68k.h" @@ -131,9 +130,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/m68k/m68k/sunos_syscall.c mult-netbsd-3.1/sys/arch/m68k/m68k/sunos_syscall.c --- NetBSD-3.1/sys/arch/m68k/m68k/sunos_syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/m68k/m68k/sunos_syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -115,7 +115,6 @@ #include "opt_syscall_debug.h" #include "opt_execfmt.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -128,9 +127,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/mips/mips/syscall.c mult-netbsd-3.1/sys/arch/mips/mips/syscall.c --- NetBSD-3.1/sys/arch/mips/mips/syscall.c 2004-04-04 06:32:20.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/mips/mips/syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -118,7 +118,6 @@ #if defined(_KERNEL_OPT) #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_syscall_debug.h" #endif @@ -130,9 +129,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/pc532/pc532/trap.c mult-netbsd-3.1/sys/arch/pc532/pc532/trap.c --- NetBSD-3.1/sys/arch/pc532/pc532/trap.c 2005-01-31 07:18:52.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/pc532/pc532/trap.c 2007-11-09 18:08:21.000000000 +0000 @@ -83,7 +83,6 @@ #include "opt_kgdb.h" #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_ns381.h" #include @@ -99,9 +98,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #ifdef KGDB #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/powerpc/ibm4xx/trap.c mult-netbsd-3.1/sys/arch/powerpc/ibm4xx/trap.c --- NetBSD-3.1/sys/arch/powerpc/ibm4xx/trap.c 2005-02-25 07:09:58.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/powerpc/ibm4xx/trap.c 2007-11-09 18:08:21.000000000 +0000 @@ -72,7 +72,6 @@ #include "opt_altivec.h" #include "opt_ddb.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_syscall_debug.h" #include @@ -87,9 +86,6 @@ #include #include #include -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/powerpc/powerpc/db_interface.c mult-netbsd-3.1/sys/arch/powerpc/powerpc/db_interface.c --- NetBSD-3.1/sys/arch/powerpc/powerpc/db_interface.c 2003-12-17 04:04:40.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/powerpc/powerpc/db_interface.c 2007-11-23 10:17:18.000000000 +0000 @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -207,18 +208,29 @@ static void db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif) { - struct proc *p; + struct proc *p; + struct isnt *i; - /* XXX LOCKING XXX */ - for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { - if (p->p_stat) { - db_printf("process %p:", p); - db_printf("pid:%d pmap:%p ctx:%d %s\n", - p->p_pid, p->p_vmspace->vm_map.pmap, - p->p_vmspace->vm_map.pmap->pm_ctx, - p->p_comm); + instlist_lock_read(); + + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + for (p = i->i_allproc.lh_first; p; + p = p->p_list.le_next) { + if (p->p_stat) { + db_printf("process %p:", p); + db_printf("pid:%d pmap:%p ctx:%d %s\n", + p->p_pid, + p->p_vmspace->vm_map.pmap, + p->p_vmspace->vm_map.pmap->pm_ctx, + p->p_comm); + } } + proclist_unlock_read(i); } + + instlist_unlock_read(); + return; } diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/powerpc/powerpc/syscall.c mult-netbsd-3.1/sys/arch/powerpc/powerpc/syscall.c --- NetBSD-3.1/sys/arch/powerpc/powerpc/syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/powerpc/powerpc/syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -34,7 +34,6 @@ #include "opt_altivec.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_multiprocessor.h" /* DO NOT INCLUDE opt_compat_XXX.h */ /* If needed, they will be included by file that includes this one */ @@ -49,9 +48,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sh3/sh3/db_interface.c mult-netbsd-3.1/sys/arch/sh3/sh3/db_interface.c --- NetBSD-3.1/sys/arch/sh3/sh3/db_interface.c 2005-03-08 22:04:22.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sh3/sh3/db_interface.c 2007-11-23 10:17:18.000000000 +0000 @@ -350,13 +350,23 @@ char * __db_procname_by_asid(int asid) { - static char notfound[] = "---"; - struct proc *p; - - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_vmspace->vm_map.pmap->pm_asid == asid) + static char notfound[] = "---"; + struct proc *p; + struct inst *i; + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(p, &i->i_allproc, p_list) { + if (p->p_vmspace->vm_map.pmap->pm_asid != asid) + continue; + proclist_unlock_read(i); + instlist_unlock_read(); return (p->p_comm); + } + proclist_unlock_read(i); } + instlist_unlock_read(); return (notfound); } @@ -577,12 +587,13 @@ void db_stackcheck_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) { - struct lwp *l; - struct user *u; - struct pcb *pcb; - uint32_t *t32; - uint8_t *t8; - int i, j; + struct lwp *l; + struct user *u; + struct pcb *pcb; + uint32_t *t32; + uint8_t *t8; + int i, j; + struct inst *inst; #define MAX_STACK (USPACE - PAGE_SIZE) #define MAX_FRAME (PAGE_SIZE - sizeof(struct user)) @@ -594,28 +605,34 @@ "stack top max used frame top max used" " nest\n"); - LIST_FOREACH(l, &alllwp, l_list) { - u = l->l_addr; - pcb = &u->u_pcb; - /* stack */ - t32 = (uint32_t *)(pcb->pcb_sf.sf_r7_bank - MAX_STACK); - for (i = 0; *t32++ == 0xa5a5a5a5; i++) - continue; - i = MAX_STACK - i * sizeof(int); - - /* frame */ - t8 = (uint8_t *)((vaddr_t)pcb + PAGE_SIZE - MAX_FRAME); - for (j = 0; *t8++ == 0x5a; j++) - continue; - j = MAX_FRAME - j; - - db_printf("%6d.%-6d 0x%08x %6d (%3d%%) 0x%08lx %6d (%3d%%) %d %s\n", - l->l_proc->p_pid, l->l_lid, - pcb->pcb_sf.sf_r7_bank, i, i * 100 / MAX_STACK, - (vaddr_t)pcb + PAGE_SIZE, j, j * 100 / MAX_FRAME, - j / sizeof(struct trapframe), - l->l_proc->p_comm); + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) { + proclist_lock_read(inst); + LIST_FOREACH(l, &inst->i_alllwp, l_list) { + u = l->l_addr; + pcb = &u->u_pcb; + /* stack */ + t32 = (uint32_t *)(pcb->pcb_sf.sf_r7_bank - MAX_STACK); + for (i = 0; *t32++ == 0xa5a5a5a5; i++) + continue; + i = MAX_STACK - i * sizeof(int); + + /* frame */ + t8 = (uint8_t *)((vaddr_t)pcb + PAGE_SIZE - MAX_FRAME); + for (j = 0; *t8++ == 0x5a; j++) + continue; + j = MAX_FRAME - j; + + db_printf("%6d.%-6d 0x%08x %6d (%3d%%) 0x%08lx %6d (%3d%%) %d %s\n", + l->l_proc->p_pid, l->l_lid, + pcb->pcb_sf.sf_r7_bank, i, i * 100 / MAX_STACK, + (vaddr_t)pcb + PAGE_SIZE, j, j * 100 / MAX_FRAME, + j / sizeof(struct trapframe), + l->l_proc->p_comm); + } + proclist_unlock_read(); } + instlist_unlock_read(); #undef MAX_STACK #undef MAX_FRAME } diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sh3/sh3/exception.c mult-netbsd-3.1/sys/arch/sh3/sh3/exception.c --- NetBSD-3.1/sys/arch/sh3/sh3/exception.c 2004-03-24 15:38:41.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sh3/sh3/exception.c 2007-11-09 18:08:21.000000000 +0000 @@ -85,7 +85,6 @@ #include "opt_kgdb.h" #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -101,9 +100,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #ifdef DDB #include #endif diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sh3/sh3/pmap.c mult-netbsd-3.1/sys/arch/sh3/sh3/pmap.c --- NetBSD-3.1/sys/arch/sh3/sh3/pmap.c 2003-12-30 12:33:19.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sh3/sh3/pmap.c 2007-11-23 10:17:18.000000000 +0000 @@ -971,8 +971,9 @@ int __pmap_asid_alloc() { - struct proc *p; - int i, j, k, n, map, asid; + struct proc *p; + int i, j, k, n, map, asid; + struct inst *inst; /* Search free ASID */ i = __pmap_asid.hint >> 5; @@ -990,17 +991,25 @@ } /* Steal ASID */ - LIST_FOREACH(p, &allproc, p_list) { - if ((asid = p->p_vmspace->vm_map.pmap->pm_asid) > 0) { - pmap_t pmap = p->p_vmspace->vm_map.pmap; - pmap->pm_asid = -1; - __pmap_asid.hint = asid; - /* Invalidate all old ASID entry */ - sh_tlb_invalidate_asid(pmap->pm_asid); - return (__pmap_asid.hint); + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) { + proclist_lock_read(inst); + LIST_FOREACH(p, &inst->i_allproc, p_list) { + if ((asid = p->p_vmspace->vm_map.pmap->pm_asid) > 0) { + pmap_t pmap = p->p_vmspace->vm_map.pmap; + pmap->pm_asid = -1; + __pmap_asid.hint = asid; + /* Invalidate all old ASID entry */ + sh_tlb_invalidate_asid(pmap->pm_asid); + proclist_unlock_read(inst); + instlist_unlock_read(); + return (__pmap_asid.hint); + } } + proclist_unlock_read(inst); } + instlist_unlock_read(); panic("No ASID allocated."); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sh5/sh5/syscall.c mult-netbsd-3.1/sys/arch/sh5/sh5/syscall.c --- NetBSD-3.1/sys/arch/sh5/sh5/syscall.c 2003-10-31 03:28:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sh5/sh5/syscall.c 2007-11-09 18:08:21.000000000 +0000 @@ -134,7 +134,6 @@ #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -149,9 +148,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sparc/sparc/trap.c mult-netbsd-3.1/sys/arch/sparc/sparc/trap.c --- NetBSD-3.1/sys/arch/sparc/sparc/trap.c 2005-02-03 16:15:06.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sparc/sparc/trap.c 2007-11-09 18:08:21.000000000 +0000 @@ -53,7 +53,6 @@ #include "opt_ddb.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_compat_svr4.h" #include "opt_compat_sunos.h" #include "opt_sparc_arch.h" @@ -76,9 +75,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sparc64/sparc64/db_interface.c mult-netbsd-3.1/sys/arch/sparc64/sparc64/db_interface.c --- NetBSD-3.1/sys/arch/sparc64/sparc64/db_interface.c 2005-10-30 18:18:13.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sparc64/sparc64/db_interface.c 2007-11-23 10:17:19.000000000 +0000 @@ -865,25 +865,31 @@ db_expr_t count; char *modif; { - struct proc *p; - struct lwp *l; - - /* XXX LOCKING XXX */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_stat) { - db_printf("process %p:", p); - db_printf("pid:%d pmap:%p ctx:%x\n", - p->p_pid, p->p_vmspace->vm_map.pmap, - p->p_vmspace->vm_map.pmap->pm_ctx); - LIST_FOREACH(l, &p->p_lwps, l_sibling) { - db_printf("\tlwp %p: lid:%d tf:%p fpstate %p " - "lastcall:%s\n", - l, l->l_lid, l->l_md.md_tf, l->l_md.md_fpstate, - (l->l_addr->u_pcb.lastcall)? - l->l_addr->u_pcb.lastcall : "Null"); + struct proc *p; + struct lwp *l; + struct inst *i; + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(p, &i->i_allproc, p_list) { + if (p->p_stat) { + db_printf("process %p:", p); + db_printf("pid:%d pmap:%p ctx:%x\n", + p->p_pid, p->p_vmspace->vm_map.pmap, + p->p_vmspace->vm_map.pmap->pm_ctx); + LIST_FOREACH(l, &p->p_lwps, l_sibling) { + db_printf("\tlwp %p: lid:%d tf:%p fpstate %p " + "lastcall:%s\n", + l, l->l_lid, l->l_md.md_tf, l->l_md.md_fpstate, + (l->l_addr->u_pcb.lastcall)? + l->l_addr->u_pcb.lastcall : "Null"); + } } } + proclist_unlock_read(i); } + instlist_unlock_read(); return; } @@ -940,31 +946,41 @@ db_expr_t count; char *modif; { - struct proc *p, *pp; + struct proc *p; + struct inst *i; if (!have_addr) { db_printf("What PID do you want to map in?\n"); return; } - - LIST_FOREACH(p, &allproc, p_list) { - pp = p->p_pptr; - if (p->p_stat && p->p_pid == addr) { + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(p, &i->i_allproc, p_list) { + if (p->p_stat && p->p_pid == addr) { #if 0 -/* XXX Do we need to do the following too?: */ - extern struct pcb *cpcb; + /* XXX Do we need to do the following too? */ + extern struct pcb *cpcb; - curlwp = p; - cpcb = (struct pcb*)p->p_addr; + curlwp = p; + cpcb = (struct pcb*)p->p_addr; #endif - if (p->p_vmspace->vm_map.pmap->pm_ctx) { - switchtoctx(p->p_vmspace->vm_map.pmap->pm_ctx); + if (p->p_vmspace->vm_map.pmap->pm_ctx) { + switchtoctx(p->p_vmspace->vm_map.pmap->pm_ctx); + proclist_unlock_read(i); + instlist_unlock_read(); + return; + } + db_printf("PID %ld has a null context.\n", addr); + proclist_unlock_read(i); + instlist_unlock_read(); return; } - db_printf("PID %ld has a null context.\n", addr); - return; } + proclist_unlock_read(i); } + instlist_unlock_read(); db_printf("PID %ld not found.\n", addr); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/sparc64/sparc64/trap.c mult-netbsd-3.1/sys/arch/sparc64/sparc64/trap.c --- NetBSD-3.1/sys/arch/sparc64/sparc64/trap.c 2005-02-12 09:38:28.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/sparc64/sparc64/trap.c 2007-11-09 18:08:21.000000000 +0000 @@ -57,7 +57,6 @@ #include "opt_ddb.h" #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_compat_svr4.h" #include "opt_compat_netbsd32.h" @@ -80,9 +79,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/vax/vax/pmap.c mult-netbsd-3.1/sys/arch/vax/vax/pmap.c --- NetBSD-3.1/sys/arch/vax/vax/pmap.c 2004-03-19 20:17:51.000000000 +0000 +++ mult-netbsd-3.1/sys/arch/vax/vax/pmap.c 2007-11-23 10:17:19.000000000 +0000 @@ -670,43 +670,51 @@ static int pmap_rmproc(struct pmap *pm) { - struct pmap *ppm; - struct lwp *l; - struct lwp *outl, *outl2; - int outpri, outpri2; - int didswap = 0; - extern int maxslp; + struct pmap *ppm; + struct lwp *l; + struct lwp *outl, *outl2; + int outpri, outpri2; + int didswap = 0; + struct inst *i; + + extern int maxslp; outl = outl2 = NULL; outpri = outpri2 = 0; - proclist_lock_read(); - LIST_FOREACH(l, &alllwp, l_list) { - if (!swappable(l, pm)) - continue; - ppm = l->l_proc->p_vmspace->vm_map.pmap; - if (ppm->pm_p0lr == 0 && ppm->pm_p1lr == NPTEPERREG) - continue; /* Already swapped */ - switch (l->l_stat) { - case LSRUN: - case LSONPROC: - if (l->l_swtime > outpri2) { - outl2 = l; - outpri2 = l->l_swtime; - } - continue; - case LSSLEEP: - case LSSTOP: - if (l->l_slptime >= maxslp) { - rmspace(l->l_proc->p_vmspace->vm_map.pmap); - didswap++; - } else if (l->l_slptime > outpri) { - outl = l; - outpri = l->l_slptime; + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + if (!swappable(l, pm)) + continue; + ppm = l->l_proc->p_vmspace->vm_map.pmap; + if (ppm->pm_p0lr == 0 && ppm->pm_p1lr == NPTEPERREG) + continue; /* Already swapped */ + switch (l->l_stat) { + case LSRUN: + case LSONPROC: + if (l->l_swtime > outpri2) { + outl2 = l; + outpri2 = l->l_swtime; + } + continue; + case LSSLEEP: + case LSSTOP: + if (l->l_slptime >= maxslp) { + rmspace(l->l_proc->p_vmspace->vm_map.pmap); + didswap++; + } else if (l->l_slptime > outpri) { + outl = l; + outpri = l->l_slptime; + } + continue; } - continue; } + proclist_unlock_read(i); } - proclist_unlock_read(); + instlist_unlock_read(); + if (didswap == 0) { if ((l = outl) == NULL) l = outl2; diff -r -u -N --exclude CVS NetBSD-3.1/sys/arch/vax/vax/trap.c mult-netbsd-3.1/sys/arch/vax/vax/trap.c --- NetBSD-3.1/sys/arch/vax/vax/trap.c 2004-09-02 03:18:38.000000000 +0100 +++ mult-netbsd-3.1/sys/arch/vax/vax/trap.c 2007-11-09 18:08:21.000000000 +0000 @@ -37,7 +37,6 @@ #include "opt_ddb.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_multiprocessor.h" #include @@ -68,9 +67,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif #ifdef TRAPDEBUG volatile int startsysc = 0, faultdebug = 0; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/common/kern_info_09.c mult-netbsd-3.1/sys/compat/common/kern_info_09.c --- NetBSD-3.1/sys/compat/common/kern_info_09.c 2003-12-04 19:38:22.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/common/kern_info_09.c 2007-11-09 18:23:29.000000000 +0000 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -102,7 +103,9 @@ char *dp, *ep; strncpy(outsname.sysname, ostype, sizeof(outsname.sysname)); - strncpy(outsname.nodename, hostname, sizeof(outsname.nodename)); + if (NULL != l) + strncpy(outsname.nodename, l->l_inst->i_host, + sizeof(outsname.nodename)); strncpy(outsname.release, osrelease, sizeof(outsname.release)); dp = outsname.version; ep = &outsname.version[sizeof(outsname.version) - 1]; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/common/kern_info_43.c mult-netbsd-3.1/sys/compat/common/kern_info_43.c --- NetBSD-3.1/sys/compat/common/kern_info_43.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/common/kern_info_43.c 2007-11-09 18:23:29.000000000 +0000 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -222,11 +223,26 @@ size = sizeof(ksi) + strlen(ostype) + strlen(cpu_model) + strlen(osrelease) + strlen(machine) + - strlen(version) + strlen(hostname) + 6; + strlen(version) + 6; + if (NULL != l) + size += inst_get_hostnamelen(l); error = 0; break; } + /* + * FIXME. Ugly hack to switch on instance + * "soft" resources versus hard-coded machine + * ones. + */ +#define COPYINST(fld, key) \ + ksi.fld = us - (u_long) usi; \ + error = inst_copyoutstr_hostname \ + (l, us, 1024, &len); \ + if (0 != error) \ + return(error); \ + us += len + #define COPY(fld) \ ksi.fld = us - (u_long) usi; \ if ((error = copyoutstr(fld, us, 1024, &len)) != 0)\ @@ -256,7 +272,7 @@ ksi.child_max = CHILD_MAX; ksi.boottime = boottime; - COPY(hostname); + COPYINST(hostname, i_host); size = (us - (char *) &usi[1]) + sizeof(ksi); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/darwin/darwin_ptrace.c mult-netbsd-3.1/sys/compat/darwin/darwin_ptrace.c --- NetBSD-3.1/sys/compat/darwin/darwin_ptrace.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/darwin/darwin_ptrace.c 2007-11-10 19:27:10.000000000 +0000 @@ -79,9 +79,12 @@ ded = (struct darwin_emuldata *)p->p_emuldata; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + switch (req) { case DARWIN_PT_ATTACHEXC: - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (t->p_emul != &emul_darwin) @@ -110,7 +113,7 @@ case DARWIN_PT_DETACH: { int had_sigexc = 0; - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(p->p_inst, SCARG(uap, pid))) == NULL) return (ESRCH); if ((t->p_emul == &emul_darwin) && @@ -141,7 +144,7 @@ case DARWIN_PT_THUPDATE: { int signo = SCARG(uap, data); - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; /* Checks from native ptrace */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/darwin/darwin_sysctl.c mult-netbsd-3.1/sys/compat/darwin/darwin_sysctl.c --- NetBSD-3.1/sys/compat/darwin/darwin_sysctl.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/darwin/darwin_sysctl.c 2007-11-18 14:10:50.000000000 +0000 @@ -828,7 +828,7 @@ de->e_vm.vm_taddr = p->p_vmspace->vm_taddr; de->e_vm.vm_daddr = p->p_vmspace->vm_daddr; de->e_vm.vm_maxsaddr = p->p_vmspace->vm_maxsaddr; - de->e_ppid = p->p_pptr->p_pid; + de->e_ppid = p->p_pptr ? p->p_pptr->p_pid : 0; de->e_pgid = p->p_pgid; de->e_jobc = p->p_pgrp->pg_jobc; if ((p->p_flag & P_CONTROLT) && (p->p_session->s_ttyp != NULL)) { @@ -917,12 +917,16 @@ char *arg; char *tmp; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + if (namelen != 1) return (EINVAL); pid = name[0]; /* check pid */ - if ((p = pfind(pid)) == NULL) + if ((p = pfind(l->l_proc->p_inst, pid)) == NULL) return (EINVAL); /* only root or same user change look at the environment */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/freebsd/freebsd_sched.c mult-netbsd-3.1/sys/compat/freebsd/freebsd_sched.c --- NetBSD-3.1/sys/compat/freebsd/freebsd_sched.c 2003-01-18 07:33:16.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/freebsd/freebsd_sched.c 2007-11-10 19:27:10.000000000 +0000 @@ -80,6 +80,10 @@ struct freebsd_sched_param lp; struct proc *p; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + /* * We only check for valid parameters and return afterwards. */ @@ -93,7 +97,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = l->l_proc->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(l->l_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(l->l_proc == p || pc->pc_ucred->cr_uid == 0 || @@ -120,6 +124,10 @@ struct proc *p; struct freebsd_sched_param lp; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + /* * We only check for valid parameters and return a dummy * priority afterwards. @@ -130,7 +138,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = l->l_proc->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(l->l_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(l->l_proc == p || pc->pc_ucred->cr_uid == 0 || @@ -160,6 +168,10 @@ struct freebsd_sched_param lp; struct proc *p; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + /* * We only check for valid parameters and return afterwards. */ @@ -173,7 +185,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = l->l_proc->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(l->l_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(l->l_proc == p || pc->pc_ucred->cr_uid == 0 || @@ -204,6 +216,10 @@ } */ *uap = v; struct proc *p; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + *retval = -1; /* @@ -212,7 +228,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = l->l_proc->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(l->l_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(l->l_proc == p || pc->pc_ucred->cr_uid == 0 || diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/hpux/hpux_compat.c mult-netbsd-3.1/sys/compat/hpux/hpux_compat.c --- NetBSD-3.1/sys/compat/hpux/hpux_compat.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/hpux/hpux_compat.c 2007-11-10 19:27:10.000000000 +0000 @@ -426,21 +426,24 @@ register_t *retval; { struct hpux_sys_utssys_args *uap = v; - int i; - int error; + int i, error; struct hpux_utsname ut; + char tmphost[MAXHOSTNAMELEN]; + size_t tmphostlen; switch (SCARG(uap, request)) { /* uname */ case 0: memset(&ut, 0, sizeof(ut)); + inst_get_hostname(l, tmphost, MAXHOSTNAMELEN); + strncpy(ut.sysname, ostype, sizeof(ut.sysname)); ut.sysname[sizeof(ut.sysname) - 1] = '\0'; /* copy hostname (sans domain) to nodename */ - for (i = 0; i < 8 && hostname[i] != '.'; i++) - ut.nodename[i] = hostname[i]; + for (i = 0; i < 8 && tmphost[i] != '.'; i++) + ut.nodename[i] = tmphost[i]; ut.nodename[i] = '\0'; strncpy(ut.release, osrelease, sizeof(ut.release)); @@ -460,12 +463,14 @@ case 5: /* SCARG(uap, dev) is length */ i = SCARG(uap, dev); + tmphostlen = inst_get_hostnamelen(l); if (i < 0) { error = EINVAL; break; - } else if (i > hostnamelen + 1) - i = hostnamelen + 1; - error = copyout((caddr_t)hostname, (caddr_t)SCARG(uap, uts), i); + } else if (i > tmphostlen + 1) + i = tmphostlen + 1; + + error = inst_copyout_hostname(l, (caddr_t)SCARG(uap, uts), i); break; case 1: /* ?? */ @@ -580,13 +585,16 @@ struct proc *p; int nice, error; + KASSERT(NULL != lp); + KASSERT(NULL != lp->l_inst); + if (SCARG(uap, prio) < RTPRIO_MIN && SCARG(uap, prio) > RTPRIO_MAX && SCARG(uap, prio) != RTPRIO_NOCHG && SCARG(uap, prio) != RTPRIO_RTOFF) return (EINVAL); if (SCARG(uap, pid) == 0) p = lp->l_proc; - else if ((p = pfind(SCARG(uap, pid))) == 0) + else if ((p = pfind(lp->l_inst, SCARG(uap, pid))) == 0) return (ESRCH); nice = p->p_nice - NZERO; if (nice < 0) @@ -931,9 +939,12 @@ struct proc *cp = lp->l_proc; struct proc *p; + KASSERT(NULL != lp); + KASSERT(NULL != lp->l_inst); + if (SCARG(uap, pid) == 0) SCARG(uap, pid) = cp->p_pid; - p = pfind(SCARG(uap, pid)); + p = pfind(lp->l_inst, SCARG(uap, pid)); if (p == 0) return (ESRCH); if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/ibcs2/ibcs2_misc.c mult-netbsd-3.1/sys/compat/ibcs2/ibcs2_misc.c --- NetBSD-3.1/sys/compat/ibcs2/ibcs2_misc.c 2005-10-01 11:39:27.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/ibcs2/ibcs2_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -132,6 +132,7 @@ #include #include +#include #if defined(__i386__) #include @@ -1667,7 +1668,9 @@ (void)memset(&uts, 0, sizeof(uts)); (void)strncpy(uts.sysname, ostype, 8); - (void)strncpy(uts.nodename, hostname, 8); + + inst_get_hostname(l, uts.nodename, 8); + (void)strncpy(uts.release, osrelease, 15); (void)strncpy(uts.kid, "kernel id 1", 19); (void)strncpy(uts.machine, machine, 8); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/ibcs2/ibcs2_stat.c mult-netbsd-3.1/sys/compat/ibcs2/ibcs2_stat.c --- NetBSD-3.1/sys/compat/ibcs2/ibcs2_stat.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/ibcs2/ibcs2_stat.c 2007-11-09 18:23:30.000000000 +0000 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -367,7 +368,9 @@ memset(&sut, 0, ibcs2_utsname_len); memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); - memcpy(sut.nodename, hostname, sizeof(sut.nodename)); + + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); + sut.nodename[sizeof(sut.nodename)-1] = '\0'; memcpy(sut.release, osrelease, sizeof(sut.release) - 1); strlcpy(sut.version, "1", sizeof(sut.version)); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/irix/irix_exec.c mult-netbsd-3.1/sys/compat/irix/irix_exec.c --- NetBSD-3.1/sys/compat/irix/irix_exec.c 2005-09-18 21:09:51.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/irix/irix_exec.c 2007-11-23 10:17:19.000000000 +0000 @@ -200,8 +200,8 @@ /* * Send SIGHUP to child process as requested using prctl(2) */ - proclist_lock_read(); - PROCLIST_FOREACH(pp, &allproc) { + proclist_lock_read(p->p_inst); + PROCLIST_FOREACH(pp, &p->p_inst->i_allproc) { /* Select IRIX processes */ if (irix_check_exec(pp) == 0) continue; @@ -210,7 +210,7 @@ if (ied->ied_termchild && pp->p_pptr == p) psignal(pp, native_to_svr4_signo[SIGHUP]); } - proclist_unlock_read(); + proclist_unlock_read(p->p_inst); /* * Remove the process from share group processes list, if revelant. diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/irix/irix_misc.c mult-netbsd-3.1/sys/compat/irix/irix_misc.c --- NetBSD-3.1/sys/compat/irix/irix_misc.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/irix/irix_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -112,8 +112,7 @@ strncpy(sut.sysname, irix_si_os_name, sizeof(sut.sysname)); sut.sysname[sizeof(sut.sysname) - 1] = '\0'; - strncpy(sut.nodename, hostname, sizeof(sut.nodename)); - sut.nodename[sizeof(sut.nodename) - 1] = '\0'; + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); strncpy(sut.release, irix_release, sizeof(sut.release)); sut.release[sizeof(sut.release) - 1] = '\0'; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/irix/irix_prctl.c mult-netbsd-3.1/sys/compat/irix/irix_prctl.c --- NetBSD-3.1/sys/compat/irix/irix_prctl.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/irix/irix_prctl.c 2007-11-19 15:54:40.000000000 +0000 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,9 @@ struct proc *p = l->l_proc; unsigned int option = SCARG(uap, option); + KASSERT(NULL != l); + KASSERT(NULL != l->l_inst); + #ifdef DEBUG_IRIX printf("irix_sys_prctl(): option = %d\n", option); #endif @@ -110,7 +114,7 @@ int shmask = 0; struct irix_emuldata *ied; - p2 = pfind((pid_t)SCARG(uap, arg1)); + p2 = pfind(l->l_inst, (pid_t)SCARG(uap, arg1)); if (p2 == p || SCARG(uap, arg1) == 0) { /* XXX return our own shmask */ @@ -177,7 +181,7 @@ if (pid == 0) pid = p->p_pid; - if ((target = pfind(pid)) == NULL) + if ((target = pfind(l->l_inst, pid)) == NULL) return ESRCH; if (irix_check_exec(target) == 0) @@ -489,8 +493,9 @@ parent->p_cred->p_refcnt++; p2->p_cred = parent->p_cred; if (--pc->p_refcnt == 0) { + /*inst_urelease(pc->pc_ucred);*/ crfree(pc->pc_ucred); - pool_put(&pcred_pool, pc); + pcred_free(pc); } } @@ -498,6 +503,7 @@ * Handle shared process limits */ if (inh & IRIX_PR_SULIMIT) { + KASSERT(NULL != parent->p_inst); pl = p2->p_limit; parent->p_limit->p_refcnt++; p2->p_limit = parent->p_limit; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/irix/irix_syssgi.c mult-netbsd-3.1/sys/compat/irix/irix_syssgi.c --- NetBSD-3.1/sys/compat/irix/irix_syssgi.c 2005-02-26 23:10:18.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/irix/irix_syssgi.c 2007-11-10 19:27:10.000000000 +0000 @@ -109,6 +109,9 @@ int request = SCARG(uap, request); void *arg1, *arg2, *arg3; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + #ifdef DEBUG_IRIX printf("irix_sys_syssgi(): request = %d\n", request); #endif @@ -217,7 +220,7 @@ arg1 = SCARG(uap, arg1); /* PID of the process */ arg2 = SCARG(uap, arg2); /* Address of user buffer */ arg3 = SCARG(uap, arg3); /* Length of user buffer */ - tp = pfind((pid_t)arg1); + tp = pfind(p->p_inst, (pid_t)arg1); if (tp == NULL || \ tp->p_psstr == NULL || \ tp->p_psstr->ps_argvstr == NULL || \ diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/arch/i386/linux_ptrace.c mult-netbsd-3.1/sys/compat/linux/arch/i386/linux_ptrace.c --- NetBSD-3.1/sys/compat/linux/arch/i386/linux_ptrace.c 2005-02-26 23:10:19.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/linux/arch/i386/linux_ptrace.c 2007-11-10 19:27:10.000000000 +0000 @@ -146,6 +146,9 @@ struct linux_fpctx *linux_fpregs = NULL; int addr; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + request = SCARG(uap, request); if ((request != LINUX_PTRACE_PEEKUSR) && @@ -157,7 +160,7 @@ return EIO; /* Find the process we're supposed to be operating on. */ - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; /* diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/common/linux_file.c mult-netbsd-3.1/sys/compat/linux/common/linux_file.c --- NetBSD-3.1/sys/compat/linux/common/linux_file.c 2005-03-10 14:12:28.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/linux/common/linux_file.c 2007-11-10 19:27:10.000000000 +0000 @@ -315,6 +315,9 @@ cmd = SCARG(uap, cmd); arg = (caddr_t) SCARG(uap, arg); + KASSERT(NULL != l); + KASSERT(NULL != l->l_inst); + switch (cmd) { case LINUX_F_DUPFD: cmd = F_DUPFD; @@ -463,12 +466,12 @@ if ((long)arg <= 0) { pgid = -(long)arg; } else { - struct proc *p1 = pfind((long)arg); + struct proc *p1 = pfind(l->l_inst, (long)arg); if (p1 == NULL) return (ESRCH); pgid = (long)p1->p_pgrp->pg_id; } - pgrp = pgfind(pgid); + pgrp = pgfind(l->l_inst, pgid); if (pgrp == NULL || pgrp->pg_session != p->p_session) return EPERM; tp->t_pgrp = pgrp; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/common/linux_misc.c mult-netbsd-3.1/sys/compat/linux/common/linux_misc.c --- NetBSD-3.1/sys/compat/linux/common/linux_misc.c 2005-11-01 22:31:17.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/linux/common/linux_misc.c 2007-11-23 10:17:19.000000000 +0000 @@ -95,6 +95,7 @@ #include #include /* for SWAP_ON */ #include /* for KERN_DOMAINNAME */ +#include #include #include @@ -444,11 +445,11 @@ struct linux_utsname luts; strncpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname)); - strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); + inst_get_hostname(l, luts.l_nodename, sizeof(luts.l_nodename)); strncpy(luts.l_release, linux_release, sizeof(luts.l_release)); strncpy(luts.l_version, linux_version, sizeof(luts.l_version)); strncpy(luts.l_machine, machine, sizeof(luts.l_machine)); - strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname)); + inst_get_domainname(l, luts.l_domainname, sizeof(luts.l_domainname)); return copyout(&luts, SCARG(uap, up), sizeof(luts)); } @@ -1074,8 +1075,11 @@ struct proc *p = l->l_proc; struct proc *targp; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) { - if ((targp = pfind(SCARG(uap, pid))) == 0) + if ((targp = pfind(p->p_inst, SCARG(uap, pid))) == 0) return ESRCH; } else @@ -1593,7 +1597,7 @@ si.bufferram = uvmexp.filepages * uvmexp.pagesize; si.totalswap = uvmexp.swpages * uvmexp.pagesize; si.freeswap = (uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize; - si.procs = nprocs; + si.procs = l->l_inst->i_nprocs; /* The following are only present in newer Linux kernels. */ si.totalbig = 0; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/common/linux_oldolduname.c mult-netbsd-3.1/sys/compat/linux/common/linux_oldolduname.c --- NetBSD-3.1/sys/compat/linux/common/linux_oldolduname.c 2003-01-19 16:41:46.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/linux/common/linux_oldolduname.c 2007-11-09 18:23:30.000000000 +0000 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -69,7 +70,7 @@ struct linux_oldoldutsname luts; strncpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname)); - strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); + inst_get_hostname(l, luts.l_nodename, sizeof(luts.l_nodename)); strncpy(luts.l_release, linux_release, sizeof(luts.l_release)); strncpy(luts.l_version, linux_version, sizeof(luts.l_version)); strncpy(luts.l_machine, machine, sizeof(luts.l_machine)); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/common/linux_olduname.c mult-netbsd-3.1/sys/compat/linux/common/linux_olduname.c --- NetBSD-3.1/sys/compat/linux/common/linux_olduname.c 2003-01-18 08:04:38.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/linux/common/linux_olduname.c 2007-11-09 18:23:30.000000000 +0000 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -72,7 +73,7 @@ struct linux_oldutsname luts; strncpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname)); - strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); + inst_get_hostname(l, luts.l_nodename, sizeof(luts.l_nodename)); strncpy(luts.l_release, linux_release, sizeof(luts.l_release)); strncpy(luts.l_version, linux_version, sizeof(luts.l_version)); strncpy(luts.l_machine, machine, sizeof(luts.l_machine)); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/linux/common/linux_sched.c mult-netbsd-3.1/sys/compat/linux/common/linux_sched.c --- NetBSD-3.1/sys/compat/linux/common/linux_sched.c 2004-09-10 23:22:20.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/linux/common/linux_sched.c 2007-11-11 13:27:02.000000000 +0000 @@ -133,6 +133,8 @@ struct linux_sched_param lp; struct proc *p; + KASSERT(NULL != cp); + KASSERT(NULL != cp->p_inst); /* * We only check for valid parameters and return afterwards. */ @@ -147,7 +149,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = cp->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(cp->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(cp == p || pc->pc_ucred->cr_uid == 0 || @@ -175,6 +177,9 @@ struct proc *p; struct linux_sched_param lp; + KASSERT(NULL != cp); + KASSERT(NULL != cp->p_inst); + /* * We only check for valid parameters and return a dummy priority afterwards. */ @@ -184,7 +189,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = cp->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(cp->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(cp == p || pc->pc_ucred->cr_uid == 0 || @@ -215,6 +220,9 @@ struct linux_sched_param lp; struct proc *p; + KASSERT(NULL != cp); + KASSERT(NULL != cp->p_inst); + /* * We only check for valid parameters and return afterwards. */ @@ -229,7 +237,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = cp->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(cp->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(cp == p || pc->pc_ucred->cr_uid == 0 || @@ -261,6 +269,9 @@ struct proc *cp = cl->l_proc; struct proc *p; + KASSERT(NULL != cp); + KASSERT(NULL != cp->p_inst); + *retval = -1; /* * We only check for valid parameters and return afterwards. @@ -269,7 +280,7 @@ if (SCARG(uap, pid) != 0) { struct pcred *pc = cp->p_cred; - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(cp->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; if (!(cp == p || pc->pc_ucred->cr_uid == 0 || diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/mach/mach_exception.c mult-netbsd-3.1/sys/compat/mach/mach_exception.c --- NetBSD-3.1/sys/compat/mach/mach_exception.c 2005-02-26 23:10:19.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/mach/mach_exception.c 2007-11-18 14:10:50.000000000 +0000 @@ -167,7 +167,8 @@ sigminusset(&contsigmask, &p->p_sigctx.ps_siglist); SCHED_LOCK(s); - p->p_pptr->p_nstopchild++; + if (p->p_pptr) + p->p_pptr->p_nstopchild++; p->p_stat = SSTOP; exc_l->l_stat = LSSTOP; p->p_nrlwps--; @@ -224,13 +225,15 @@ * a dying parent, a signal is sent instead of the * notification, this fixes the problem. */ - if ((exc_l->l_proc->p_flag & P_TRACED) && - (exc_l->l_proc->p_pptr->p_flag & P_WEXIT)) { + if (exc_l->l_proc->p_flag & P_TRACED) { + KASSERT(exc_l->l_proc->p_pptr); + if (exc_l->l_proc->p_pptr->p_flag & P_WEXIT) { #ifdef DEBUG_MACH - printf("mach_exception: deadlock avoided\n"); + printf("mach_exception: deadlock avoided\n"); #endif - error = EINVAL; - goto out; + error = EINVAL; + goto out; + } } if (exc_port->mp_datatype != MACH_MP_EXC_INFO) { diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/mach/mach_message.c mult-netbsd-3.1/sys/compat/mach/mach_message.c --- NetBSD-3.1/sys/compat/mach/mach_message.c 2005-02-26 23:10:19.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/mach/mach_message.c 2007-11-23 10:17:19.000000000 +0000 @@ -1243,50 +1243,57 @@ void mach_debug_message(void) { - struct lwp *l; + struct lwp *l; + struct inst *i; struct mach_emuldata *med; struct mach_right *mr; struct mach_right *mrs; struct mach_port *mp; struct mach_message *mm; - LIST_FOREACH(l, &alllwp, l_list) { - if ((l->l_proc->p_emul != &emul_mach) && + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + if ((l->l_proc->p_emul != &emul_mach) && #ifdef COMPAT_DARWIN - (l->l_proc->p_emul != &emul_darwin) && + (l->l_proc->p_emul != &emul_darwin) && #endif - 1) - continue; - - med = l->l_proc->p_emuldata; - LIST_FOREACH(mr, &med->med_right, mr_list) - if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { - mp = mr->mr_port; - if (mp == NULL) - continue; - - printf("port %p(%d) ", mp, mp->mp_count); - - TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) - printf("%d ", mm->mm_msg->msgh_id); - - printf("\n"); + 1) continue; - } - /* Port set... */ - LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { - mp = mrs->mr_port; - if (mp == NULL) + + med = l->l_proc->p_emuldata; + LIST_FOREACH(mr, &med->med_right, mr_list) + if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { + mp = mr->mr_port; + if (mp == NULL) + continue; + + printf("port %p(%d) ", mp, mp->mp_count); + + TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) + printf("%d ", mm->mm_msg->msgh_id); + + printf("\n"); continue; - - printf("port %p(%d) ", mp, mp->mp_count); - - TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) - printf("%d ", mm->mm_msg->msgh_id); - - printf("\n"); - } + } + /* Port set... */ + LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { + mp = mrs->mr_port; + if (mp == NULL) + continue; + + printf("port %p(%d) ", mp, mp->mp_count); + + TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) + printf("%d ", mm->mm_msg->msgh_id); + + printf("\n"); + } + } + proclist_unlock_read(i); } + instlist_unlock_read(); return; } diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/mach/mach_port.c mult-netbsd-3.1/sys/compat/mach/mach_port.c --- NetBSD-3.1/sys/compat/mach/mach_port.c 2005-02-26 23:10:20.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/mach/mach_port.c 2007-11-23 10:17:19.000000000 +0000 @@ -1000,47 +1000,54 @@ struct mach_emuldata *med; struct mach_right *mr; struct mach_right *mrs; - struct proc *p; + struct proc *p; + struct inst *i; - PROCLIST_FOREACH(p, &allproc) { - if ((p->p_emul != &emul_mach) && + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + PROCLIST_FOREACH(p, &i->i_allproc) { + if ((p->p_emul != &emul_mach) && #ifdef COMPAT_DARWIN - (p->p_emul != &emul_darwin) && + (p->p_emul != &emul_darwin) && #endif - 1) - continue; - - med = p->p_emuldata; - LIST_FOREACH(mr, &med->med_right, mr_list) { - if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { - printf("pid %d: %p(%x)=>%p", - p->p_pid, mr, mr->mr_type, mr->mr_port); - if (mr->mr_port && mr->mr_port->mp_recv) - printf("[%p]\n", - mr->mr_port->mp_recv->mr_sethead); - else - printf("[NULL]\n"); - + 1) continue; - } - - /* Port set... */ - printf("pid %d: set %p(%x) ", - p->p_pid, mr, mr->mr_type); - LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { - printf("%p(%x)=>%p", - mrs, mrs->mr_type, mrs->mr_port); - if (mrs->mr_port && mrs->mr_port->mp_recv) - printf("[%p]", - mrs->mr_port->mp_recv->mr_sethead); - else - printf("[NULL]"); - printf(" "); + med = p->p_emuldata; + LIST_FOREACH(mr, &med->med_right, mr_list) { + if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { + printf("pid %d: %p(%x)=>%p", + p->p_pid, mr, mr->mr_type, mr->mr_port); + if (mr->mr_port && mr->mr_port->mp_recv) + printf("[%p]\n", + mr->mr_port->mp_recv->mr_sethead); + else + printf("[NULL]\n"); + + continue; + } + + /* Port set... */ + printf("pid %d: set %p(%x) ", + p->p_pid, mr, mr->mr_type); + LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { + printf("%p(%x)=>%p", + mrs, mrs->mr_type, mrs->mr_port); + if (mrs->mr_port && mrs->mr_port->mp_recv) + printf("[%p]", + mrs->mr_port->mp_recv->mr_sethead); + else + printf("[NULL]"); + + printf(" "); + } + printf("\n"); } - printf("\n"); } + proclist_unlock_read(i); } + instlist_unlock_read(); return; } diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/mach/mach_task.c mult-netbsd-3.1/sys/compat/mach/mach_task.c --- NetBSD-3.1/sys/compat/mach/mach_task.c 2005-02-26 23:10:20.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/mach/mach_task.c 2007-11-10 19:27:10.000000000 +0000 @@ -668,6 +668,9 @@ struct proc *t; int error; + KASSERT(NULL != l); + KASSERT(NULL != l->l_inst); + /* * target_tport is used because the task may be on * a different host. (target_tport, pid) is unique. @@ -679,7 +682,7 @@ l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) return EPERM; - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(l->l_inst, SCARG(uap, pid))) == NULL) return ESRCH; /* Allowed only if the UID match, if setuid, or if superuser */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/netbsd32/netbsd32_execve.c mult-netbsd-3.1/sys/compat/netbsd32/netbsd32_execve.c --- NetBSD-3.1/sys/compat/netbsd32/netbsd32_execve.c 2005-09-12 14:45:06.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/netbsd32/netbsd32_execve.c 2007-11-18 14:10:50.000000000 +0000 @@ -387,6 +387,7 @@ p->p_flag |= P_EXEC; if (p->p_flag & P_PPWAIT) { p->p_flag &= ~P_PPWAIT; + KASSERT(p->p_pptr); wakeup((caddr_t) p->p_pptr); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/osf1/osf1_misc.c mult-netbsd-3.1/sys/compat/osf1/osf1_misc.c --- NetBSD-3.1/sys/compat/osf1/osf1_misc.c 2006-04-25 08:51:47.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/osf1/osf1_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -287,9 +287,10 @@ register_t *retval; { struct osf1_sys_sysinfo_args *uap = v; - const char *string; - size_t slen; - int error; + const char *string; + char buf[MAXHOSTNAMELEN]; + size_t slen; + int error; error = 0; switch (SCARG(uap, cmd)) { @@ -298,7 +299,8 @@ break; case OSF1_SI_HOSTNAME: - string = hostname; + inst_get_hostname(l, buf, MAXHOSTNAMELEN); + string = &buf[0]; break; case OSF1_SI_RELEASE: @@ -371,7 +373,9 @@ /* XXX would use stackgap, but our struct utsname is too big! */ strncpy(u.sysname, ostype, sizeof(u.sysname)); - strncpy(u.nodename, hostname, sizeof(u.nodename)); + + inst_get_hostname(l, u.nodename, sizeof(u.nodename)); + strncpy(u.release, osrelease, sizeof(u.release)); dp = u.version; ep = &u.version[sizeof(u.version) - 1]; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/sunos/sunos_misc.c mult-netbsd-3.1/sys/compat/sunos/sunos_misc.c --- NetBSD-3.1/sys/compat/sunos/sunos_misc.c 2005-10-01 11:39:27.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/sunos/sunos_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -810,8 +810,7 @@ memset(&sut, 0, sizeof(sut)); memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); - memcpy(sut.nodename, hostname, sizeof(sut.nodename)); - sut.nodename[sizeof(sut.nodename)-1] = '\0'; + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); memcpy(sut.release, osrelease, sizeof(sut.release) - 1); memcpy(sut.version, "1", sizeof(sut.version) - 1); memcpy(sut.machine, machine, sizeof(sut.machine) - 1); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/sunos32/sunos32_misc.c mult-netbsd-3.1/sys/compat/sunos32/sunos32_misc.c --- NetBSD-3.1/sys/compat/sunos32/sunos32_misc.c 2005-10-01 11:39:27.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/sunos32/sunos32_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -1058,7 +1058,7 @@ memset(&sut, 0, sizeof(sut)); memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); - memcpy(sut.nodename, hostname, sizeof(sut.nodename)); + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); sut.nodename[sizeof(sut.nodename)-1] = '\0'; memcpy(sut.release, osrelease, sizeof(sut.release) - 1); memcpy(sut.version, "1", sizeof(sut.version) - 1); diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/svr4/svr4_misc.c mult-netbsd-3.1/sys/compat/svr4/svr4_misc.c --- NetBSD-3.1/sys/compat/svr4/svr4_misc.c 2005-10-01 11:39:26.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/svr4/svr4_misc.c 2007-11-10 19:27:10.000000000 +0000 @@ -114,7 +114,8 @@ struct svr4_statvfs *)); static void bsd_statvfs_to_svr4_statvfs64 __P((const struct statvfs *, struct svr4_statvfs64 *)); -#define svr4_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE) +#define svr4_pfind(inst, pid) \ + p_find((inst), (pid), PFIND_UNLOCK | PFIND_ZOMBIE) static int svr4_mknod __P((struct lwp *, register_t *, const char *, svr4_mode_t, svr4_dev_t)); @@ -964,6 +965,9 @@ struct svr4_sys_pgrpsys_args *uap = v; struct proc *p = l->l_proc; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + switch (SCARG(uap, cmd)) { case 1: /* setpgrp() */ /* @@ -982,7 +986,7 @@ case 2: /* getsid(pid) */ if (SCARG(uap, pid) != 0 && - (p = svr4_pfind(SCARG(uap, pid))) == NULL) + (p = svr4_pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; /* * This has already been initialized to the pid of @@ -997,7 +1001,7 @@ case 4: /* getpgid(pid) */ if (SCARG(uap, pid) != 0 && - (p = svr4_pfind(SCARG(uap, pid))) == NULL) + (p = svr4_pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; *retval = (int) p->p_pgrp->pg_id; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/svr4/svr4_stat.c mult-netbsd-3.1/sys/compat/svr4/svr4_stat.c --- NetBSD-3.1/sys/compat/svr4/svr4_stat.c 2005-02-26 23:10:21.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/svr4/svr4_stat.c 2007-11-09 18:23:30.000000000 +0000 @@ -59,6 +59,7 @@ #include #include +#include #include #include @@ -562,8 +563,7 @@ strncpy(sut.sysname, ostype, sizeof(sut.sysname)); sut.sysname[sizeof(sut.sysname) - 1] = '\0'; - strncpy(sut.nodename, hostname, sizeof(sut.nodename)); - sut.nodename[sizeof(sut.nodename) - 1] = '\0'; + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); strncpy(sut.release, osrelease, sizeof(sut.release)); sut.release[sizeof(sut.release) - 1] = '\0'; @@ -586,11 +586,10 @@ register_t *retval; { struct svr4_sys_systeminfo_args *uap = v; - const char *str = NULL; - int name[2]; - int error; - size_t len; - char buf[256]; + const char *str = NULL; + int name[2], error; + size_t len; + char buf[256], hostbuf[MAXHOSTNAMELEN]; u_int rlen = SCARG(uap, len); @@ -600,7 +599,8 @@ break; case SVR4_SI_HOSTNAME: - str = hostname; + inst_get_hostname(l, hostbuf, MAXHOSTNAMELEN); + str = &hostbuf[0]; break; case SVR4_SI_RELEASE: @@ -629,7 +629,8 @@ break; case SVR4_SI_SRPC_DOMAIN: - str = domainname; + inst_get_domainname(l, hostbuf, MAXHOSTNAMELEN); + str = &hostbuf[0]; break; case SVR4_SI_PLATFORM: diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/svr4_32/svr4_32_misc.c mult-netbsd-3.1/sys/compat/svr4_32/svr4_32_misc.c --- NetBSD-3.1/sys/compat/svr4_32/svr4_32_misc.c 2005-10-01 11:39:27.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/svr4_32/svr4_32_misc.c 2007-11-10 19:27:11.000000000 +0000 @@ -114,7 +114,8 @@ struct svr4_32_statvfs *)); static void bsd_statvfs_to_svr4_32_statvfs64 __P((const struct statvfs *, struct svr4_32_statvfs64 *)); -#define svr4_32_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE) +#define svr4_32_pfind(inst, pid) \ + p_find((inst), (pid), PFIND_UNLOCK | PFIND_ZOMBIE) static int svr4_32_mknod __P((struct lwp *, register_t *, const char *, svr4_32_mode_t, svr4_32_dev_t)); @@ -980,6 +981,9 @@ struct svr4_32_sys_pgrpsys_args *uap = v; struct proc *p = l->l_proc; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + switch (SCARG(uap, cmd)) { case 1: /* setpgrp() */ /* @@ -998,7 +1002,7 @@ case 2: /* getsid(pid) */ if (SCARG(uap, pid) != 0 && - (p = svr4_32_pfind(SCARG(uap, pid))) == NULL) + (p = svr4_32_pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; /* * This has already been initialized to the pid of @@ -1013,7 +1017,7 @@ case 4: /* getpgid(pid) */ if (SCARG(uap, pid) != 0 && - (p = svr4_32_pfind(SCARG(uap, pid))) == NULL) + (p = svr4_32_pfind(p->p_inst, SCARG(uap, pid))) == NULL) return ESRCH; *retval = (int) p->p_pgrp->pg_id; diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/svr4_32/svr4_32_stat.c mult-netbsd-3.1/sys/compat/svr4_32/svr4_32_stat.c --- NetBSD-3.1/sys/compat/svr4_32/svr4_32_stat.c 2005-02-26 23:10:21.000000000 +0000 +++ mult-netbsd-3.1/sys/compat/svr4_32/svr4_32_stat.c 2007-11-09 18:23:30.000000000 +0000 @@ -582,8 +582,7 @@ strncpy(sut.sysname, ostype, sizeof(sut.sysname)); sut.sysname[sizeof(sut.sysname) - 1] = '\0'; - strncpy(sut.nodename, hostname, sizeof(sut.nodename)); - sut.nodename[sizeof(sut.nodename) - 1] = '\0'; + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); strncpy(sut.release, osrelease, sizeof(sut.release)); sut.release[sizeof(sut.release) - 1] = '\0'; @@ -606,12 +605,11 @@ register_t *retval; { struct svr4_32_sys_systeminfo_args *uap = v; - struct proc *p = l->l_proc; - const char *str = NULL; - int name[2]; - int error; - size_t len; - char buf[256]; + struct proc *p = l->l_proc; + const char *str = NULL; + int name[2], error; + size_t len; + char buf[256], hostbuf[MAXHOSTNAMELEN]; u_int rlen = SCARG(uap, len); @@ -621,7 +619,8 @@ break; case SVR4_SI_HOSTNAME: - str = hostname; + inst_get_hostname(l, hostbuf, MAXHOSTNAMELEN); + str = &hostbuf[0]; break; case SVR4_SI_RELEASE: diff -r -u -N --exclude CVS NetBSD-3.1/sys/compat/ultrix/ultrix_misc.c mult-netbsd-3.1/sys/compat/ultrix/ultrix_misc.c --- NetBSD-3.1/sys/compat/ultrix/ultrix_misc.c 2005-09-18 21:09:50.000000000 +0100 +++ mult-netbsd-3.1/sys/compat/ultrix/ultrix_misc.c 2007-11-09 18:23:30.000000000 +0000 @@ -423,7 +423,7 @@ memset(&sut, 0, sizeof(sut)); strncpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); - strncpy(sut.nodename, hostname, sizeof(sut.nodename) - 1); + inst_get_hostname(l, sut.nodename, sizeof(sut.nodename)); strncpy(sut.release, osrelease, sizeof(sut.release) - 1); dp = sut.version; ep = &sut.version[sizeof(sut.version) - 1]; diff -r -u -N --exclude CVS NetBSD-3.1/sys/conf/files mult-netbsd-3.1/sys/conf/files --- NetBSD-3.1/sys/conf/files 2006-04-09 00:32:10.000000000 +0100 +++ mult-netbsd-3.1/sys/conf/files 2007-11-18 17:09:08.000000000 +0000 @@ -18,7 +18,6 @@ defflag KMEMSTATS defflag KCONT defflag KTRACE -defflag SYSTRACE defparam MAXUPRC defparam RTC_OFFSET defparam HZ @@ -1138,11 +1137,11 @@ include "fs/smbfs/files.smbfs" include "fs/union/files.union" include "miscfs/fdesc/files.fdesc" -include "miscfs/kernfs/files.kernfs" +#include "miscfs/kernfs/files.kernfs" include "miscfs/nullfs/files.nullfs" include "miscfs/overlay/files.overlay" include "miscfs/portal/files.portal" -include "miscfs/procfs/files.procfs" +#include "miscfs/procfs/files.procfs" include "miscfs/umapfs/files.umapfs" include "nfs/files.nfs" include "ufs/files.ufs" @@ -1219,6 +1218,7 @@ file kern/kern_exec.c file kern/kern_exit.c file kern/kern_fork.c +file kern/kern_inst.c file kern/kern_kcont.c kcont file kern/kern_kthread.c file kern/kern_ktrace.c @@ -1236,7 +1236,6 @@ file kern/kern_resource.c file kern/kern_sa.c file kern/kern_sig.c -file kern/kern_systrace.c systrace file kern/kern_subr.c file kern/kern_synch.c file kern/kern_sysctl.c diff -r -u -N --exclude CVS NetBSD-3.1/sys/ddb/db_xxx.c mult-netbsd-3.1/sys/ddb/db_xxx.c --- NetBSD-3.1/sys/ddb/db_xxx.c 2005-02-26 23:04:17.000000000 +0000 +++ mult-netbsd-3.1/sys/ddb/db_xxx.c 2007-11-11 13:27:02.000000000 +0000 @@ -92,7 +92,8 @@ /*NOTREACHED*/ } - p = pfind((pid_t)pid); + /* FIXME - instances */ + p = pfind(NULL, (pid_t)pid); if (p == NULL) { db_error("no such proc\n"); /*NOTREACHED*/ @@ -113,6 +114,8 @@ void db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) { + /* FIXME - instances */ +#if 0 int i; char *mode; @@ -224,6 +227,7 @@ } } } +#endif } void diff -r -u -N --exclude CVS NetBSD-3.1/sys/dev/cons.c mult-netbsd-3.1/sys/dev/cons.c --- NetBSD-3.1/sys/dev/cons.c 2005-02-27 00:26:58.000000000 +0000 +++ mult-netbsd-3.1/sys/dev/cons.c 2007-12-09 13:38:53.000000000 +0000 @@ -90,6 +90,7 @@ #include #include #include +#include #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/dev/wscons/wsdisplay_compat_usl.c mult-netbsd-3.1/sys/dev/wscons/wsdisplay_compat_usl.c --- NetBSD-3.1/sys/dev/wscons/wsdisplay_compat_usl.c 2005-01-02 15:43:49.000000000 +0000 +++ mult-netbsd-3.1/sys/dev/wscons/wsdisplay_compat_usl.c 2007-11-10 19:27:11.000000000 +0000 @@ -137,7 +137,8 @@ static int usl_sync_check(struct usl_syncdata *sd) { - if (sd->s_proc == pfind(sd->s_pid)) + /* FIXME - instances */ + if (sd->s_proc == pfind(NULL, sd->s_pid)) return (1); printf("usl_sync_check: process %d died\n", sd->s_pid); usl_sync_done(sd); diff -r -u -N --exclude CVS NetBSD-3.1/sys/dist/ipf/netinet/ip_fil_netbsd.c mult-netbsd-3.1/sys/dist/ipf/netinet/ip_fil_netbsd.c --- NetBSD-3.1/sys/dist/ipf/netinet/ip_fil_netbsd.c 2005-04-04 19:25:38.000000000 +0100 +++ mult-netbsd-3.1/sys/dist/ipf/netinet/ip_fil_netbsd.c 2007-11-26 15:08:35.000000000 +0000 @@ -426,17 +426,12 @@ /* * Filter ioctl interface. */ -int iplioctl(dev, cmd, data, mode -#if (NetBSD >= 199511) -, p) -struct proc *p; -#else -) -#endif +int iplioctl(dev, cmd, data, mode, p) dev_t dev; u_long cmd; caddr_t data; int mode; +struct proc *p; { int s; int error = 0, unit = 0, tmp; diff -r -u -N --exclude CVS NetBSD-3.1/sys/fs/cd9660/cd9660_rrip.c mult-netbsd-3.1/sys/fs/cd9660/cd9660_rrip.c --- NetBSD-3.1/sys/fs/cd9660/cd9660_rrip.c 2005-02-26 22:58:55.000000000 +0000 +++ mult-netbsd-3.1/sys/fs/cd9660/cd9660_rrip.c 2007-11-09 18:23:30.000000000 +0000 @@ -180,9 +180,12 @@ case ISO_SUSP_CFLAG_HOST: /* Inserting hostname i.e. "kurt.tools.de" */ +#if 0 + /* FIXME - needs to be instance-ified */ inbuf = hostname; wlen = hostnamelen; - break; +#endif + return(0); case ISO_SUSP_CFLAG_CONTINUE: cont = 1; @@ -252,9 +255,12 @@ case ISO_SUSP_CFLAG_HOST: /* Inserting hostname i.e. "kurt.tools.de" */ +#if 0 + /* FIXME - needs to be instance-ified */ inbuf = hostname; wlen = hostnamelen; - break; +#endif + return(0); case ISO_SUSP_CFLAG_CONTINUE: cont = 1; diff -r -u -N --exclude CVS NetBSD-3.1/sys/fs/ptyfs/ptyfs_subr.c mult-netbsd-3.1/sys/fs/ptyfs/ptyfs_subr.c --- NetBSD-3.1/sys/fs/ptyfs/ptyfs_subr.c 2004-11-11 19:19:59.000000000 +0000 +++ mult-netbsd-3.1/sys/fs/ptyfs/ptyfs_subr.c 2007-11-09 18:23:30.000000000 +0000 @@ -144,7 +144,8 @@ p); if ((error = namei(&nd)) != 0) goto out; - cred = crget(); + + cred = crdupinst(p); error = VOP_GETATTR(nd.ni_vp, &va, cred, p); crfree(cred); VOP_UNLOCK(nd.ni_vp, 0); diff -r -u -N --exclude CVS NetBSD-3.1/sys/fs/union/union_vfsops.c mult-netbsd-3.1/sys/fs/union/union_vfsops.c --- NetBSD-3.1/sys/fs/union/union_vfsops.c 2006-01-08 15:45:11.000000000 +0000 +++ mult-netbsd-3.1/sys/fs/union/union_vfsops.c 2007-11-18 14:10:50.000000000 +0000 @@ -227,6 +227,7 @@ } um->um_cred = p->p_ucred; + /* FIXME - instances */ crhold(um->um_cred); um->um_cmode = UN_DIRMODE &~ p->p_cwdi->cwdi_cmask; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/core_elf32.c mult-netbsd-3.1/sys/kern/core_elf32.c --- NetBSD-3.1/sys/kern/core_elf32.c 2004-09-17 15:11:24.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/core_elf32.c 2007-11-18 14:10:50.000000000 +0000 @@ -317,7 +317,7 @@ sizeof(cpi.cpi_sigcatch)); cpi.cpi_pid = p->p_pid; - cpi.cpi_ppid = p->p_pptr->p_pid; + cpi.cpi_ppid = p->p_pptr ? p->p_pptr->p_pid : 0; cpi.cpi_pgrp = p->p_pgid; cpi.cpi_sid = p->p_session->s_sid; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/init_main.c mult-netbsd-3.1/sys/kern/init_main.c --- NetBSD-3.1/sys/kern/init_main.c 2006-01-20 20:48:41.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/init_main.c 2007-12-16 14:56:45.000000000 +0000 @@ -81,7 +81,6 @@ #include "opt_multiprocessor.h" #include "opt_pipe.h" #include "opt_syscall_debug.h" -#include "opt_systrace.h" #include "opt_posix.h" #include "opt_kcont.h" #include "opt_verified_exec.h" @@ -117,6 +116,7 @@ #include #include #include +#include #ifdef FAST_IPSEC #include #endif @@ -132,9 +132,6 @@ #ifdef P1003_1B_SEMAPHORE #include #endif -#ifdef SYSTRACE -#include -#endif #include #include #if NOPENCRYPTO > 0 @@ -186,7 +183,6 @@ #ifndef curlwp struct lwp *curlwp = &lwp0; #endif -struct proc *initproc; int nofile = NOFILE; int maxuprc = MAXUPRC; @@ -216,55 +212,58 @@ void main(void) { - struct lwp *l; - struct proc *p; - struct pdevinit *pdev; - int s, error; - u_int i; - rlim_t lim; - extern struct pdevinit pdevinit[]; - extern void schedcpu(void *); -#if defined(NFSSERVER) || defined(NFS) - extern void nfs_init(void); -#endif + struct lwp *l; + struct proc *p; + struct pdevinit *pdev; + int s, error; + u_int i; + rlim_t lim; #ifdef NVNODE_IMPLICIT - int usevnodes; + int usevnodes; #endif + extern struct pdevinit pdevinit[]; - /* - * Initialize the current LWP pointer (curlwp) before - * any possible traps/probes to simplify trap processing. - */ + extern void schedcpu(void *); +#if defined(NFSSERVER) || defined(NFS) + extern void nfs_init(void); +#endif + + /* Initialize the current LWP pointer (curlwp) before any possible + * traps/probes to simplify trap processing. These will later + * refer to the swapper; they have a limited instance. */ l = &lwp0; curlwp = l; l->l_cpu = curcpu(); l->l_proc = &proc0; l->l_lid = 1; - /* - * Attempt to find console and initialize - * in case of early panic or other messages. - */ + /* Attempt to find console and initialize in case of early panic or + * other messages. */ consinit(); + printf("%s", copyright); + printf("NETBSD-MULT IS ALPHA SOFTWARE: USE AT YOUR OWN RISK!\n"); + KERNEL_LOCK_INIT(); + /* Initialise the virtual memory manager. */ uvm_init(); /* Do machine-dependent initialization. */ cpu_startup(); + /* Initialise the instance subsystem. */ + inst_init(); + /* Initialize callouts. */ callout_startup(); /* Initialize the buffer cache */ bufinit(); - /* - * Initialize mbuf's. Do this now because we might attempt to - * allocate mbufs or mbuf clusters during autoconfiguration. - */ + /* Initialize mbuf's. Do this now because we might attempt to + * allocate mbufs or mbuf clusters during autoconfiguration. */ mbinit(); /* Initialize sockets. */ @@ -275,48 +274,51 @@ kcont_init(); #endif - /* - * The following things must be done before autoconfiguration. - */ - evcnt_init(); /* initialize event counters */ - tty_init(); /* initialize tty list */ + /* These things must be done before autoconfiguration. */ + + /* Initialize event counters. */ + evcnt_init(); + + /* Initialise tty list. */ + tty_init(); #if NRND > 0 - rnd_init(); /* initialize RNG */ + /* Initialise RNGs. */ + rnd_init(); #endif #if NOPENCRYPTO > 0 - /* Initialize crypto subsystem before configuring crypto hardware. */ + /* Initialize crypto subsystem before crypto hardware. */ (void)crypto_init(); #endif /* Initialize the sysctl subsystem. */ sysctl_init(); - - /* Initialize process and pgrp structures. */ - procinit(); - #ifdef LKM /* Initialize the LKM system. */ lkm_init(); #endif - - /* - * Create process 0 (the swapper). - */ + /* Create process 0 (the swapper). */ p = &proc0; + + /* Create credentials and generate the initial instance. */ + cred0.p_refcnt = 1; + p->p_cred = &cred0; + p->p_ucred = crget(inst_alloc(INST_NOWAIT)); + p->p_ucred->cr_ngroups = 1; + p->p_ucred->cr_inst->i_nprocs = 1; + strncpy(p->p_comm, "swapper", MAXCOMLEN); + proc0_insert(p, l, &pgrp0, &session0); - /* - * Set P_NOCLDWAIT so that kernel threads are reparented to - * init(8) when they exit. init(8) can easily wait them out - * for us. - */ + /* Set P_NOCLDWAIT so that kernel threads are reparented to + * init(8) when they exit. init(8) can easily wait them out for + * us. XXX - this doesn't work with instances. */ p->p_flag = P_SYSTEM | P_NOCLDWAIT; p->p_stat = SACTIVE; p->p_nice = NZERO; p->p_emul = &emul_netbsd; + #ifdef __HAVE_SYSCALL_INTERN (*p->p_emul->e_syscall_intern)(p); #endif - strncpy(p->p_comm, "swapper", MAXCOMLEN); l->l_flag = L_INMEM; l->l_stat = LSONPROC; @@ -324,12 +326,6 @@ callout_init(&l->l_tsleep_ch); - /* Create credentials. */ - cred0.p_refcnt = 1; - p->p_cred = &cred0; - p->p_ucred = crget(); - p->p_ucred->cr_ngroups = 1; /* group 0 */ - /* Create the file descriptor table. */ p->p_fd = &filedesc0.fd_fd; fdinit1(&filedesc0); @@ -378,7 +374,7 @@ /* * Charge root for one process. */ - (void)chgproccnt(0, 1); + (void)chgproccnt(p->p_inst, 0, 1); rqinit(); @@ -464,9 +460,6 @@ /* Initialize system accouting. */ acct_init(); -#ifdef SYSTRACE - systrace_init(); -#endif /* * Initialize signal-related data structures, and signal state * for proc0. @@ -487,7 +480,9 @@ * wait for us to inform it that the root file system has been * mounted. */ - if (fork1(l, 0, SIGCHLD, NULL, 0, start_init, NULL, NULL, &initproc)) + /* FIXME - initproc doesn't exist in the kernel's instance */ + if (forkinst1(start_init, NULL, "/", NULL, + &proc0.p_inst->i_initproc)) panic("fork init"); /* @@ -558,18 +553,19 @@ * info. All other processes are kthreads, which merely * share proc0's CWD info. */ - initproc->p_cwdi->cwdi_cdir = rootvnode; - VREF(initproc->p_cwdi->cwdi_cdir); - initproc->p_cwdi->cwdi_rdir = NULL; + proc0.p_inst->i_initproc->p_cwdi->cwdi_cdir = rootvnode; + VREF(proc0.p_inst->i_initproc->p_cwdi->cwdi_cdir); + proc0.p_inst->i_initproc->p_cwdi->cwdi_rdir = NULL; /* * Now can look at time, having had a chance to verify the time * from the file system. Reset p->p_rtime as it may have been * munched in mi_switch() after the time got set. */ - proclist_lock_read(); + proclist_lock_read(proc0.p_inst); + s = splsched(); - LIST_FOREACH(p, &allproc, p_list) { + LIST_FOREACH(p, &proc0.p_inst->i_allproc, p_list) { KASSERT((p->p_flag & P_MARKER) == 0); p->p_stats->p_start = mono_time = boottime = time; LIST_FOREACH(l, &p->p_lwps, l_sibling) { @@ -579,7 +575,7 @@ p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; } splx(s); - proclist_unlock_read(); + proclist_unlock_read(proc0.p_inst); /* Create the pageout daemon kernel thread. */ uvm_swap_init(); @@ -587,8 +583,8 @@ panic("fork pagedaemon"); /* Create the filesystem syncer kernel thread. */ - if (kthread_create1(sched_sync, NULL, NULL, "ioflush")) - panic("fork syncer"); + if (kthread_create1(instdaemon, NULL, NULL, "instdaemon")) + panic("fork instdaemon"); /* Create the aiodone daemon kernel thread. */ if (kthread_create1(uvm_aiodone_daemon, NULL, &uvm.aiodoned_proc, @@ -604,6 +600,11 @@ exec_init(1); /* + * Label our instance as running. + */ + proc0.p_inst->i_state = INST_RUNNING; + + /* * Okay, now we can let init(8) exec! It's off to userland! */ start_init_exec = 1; @@ -653,26 +654,28 @@ static void start_init(void *arg) { - struct lwp *l = arg; - struct proc *p = l->l_proc; - vaddr_t addr; + struct lwp *l = arg; + struct proc *p = l->l_proc; + vaddr_t addr; struct sys_execve_args /* { syscallarg(const char *) path; syscallarg(char * const *) argp; syscallarg(char * const *) envp; } */ args; - int options, i, error; - register_t retval[2]; - char flags[4], *flagsp; - const char *path, *slash; - char *ucp, **uap, *arg0, *arg1 = NULL; - char ipath[129]; - int ipx, len; + int options, i, error; + register_t retval[2]; + char flags[4], *flagsp; + const char *path, *slash; + char *ucp, **uap, *arg0, *arg1 = NULL; + char ipath[129]; + int ipx, len; /* * Now in process 1. */ strncpy(p->p_comm, "init", MAXCOMLEN); + p->p_inst->i_initproc = p; + p->p_inst->i_state = INST_RUNNING; /* * Wait for main() to tell us that it's safe to exec. diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/init_sysctl.c mult-netbsd-3.1/sys/kern/init_sysctl.c --- NetBSD-3.1/sys/kern/init_sysctl.c 2006-04-07 13:31:52.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/init_sysctl.c 2007-12-18 18:02:09.000000000 +0000 @@ -70,6 +70,7 @@ #include #include #include +#include #define VERIEXEC_NEED_NODE #include @@ -93,6 +94,7 @@ */ #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) #define KERN_LWPSLOP (5 * sizeof(struct kinfo_lwp)) +#define KERN_INSTSLOP (5 * sizeof(struct kinfo_inst)) #ifndef MULTIPROCESSOR #define sysctl_ncpus() (1) @@ -119,7 +121,7 @@ static int sysctl_kern_maxproc(SYSCTLFN_PROTO); static int sysctl_kern_securelevel(SYSCTLFN_PROTO); static int sysctl_kern_hostid(SYSCTLFN_PROTO); -static int sysctl_setlen(SYSCTLFN_PROTO); +static int sysctl_kern_hostname(SYSCTLFN_PROTO); static int sysctl_kern_clockrate(SYSCTLFN_PROTO); static int sysctl_kern_file(SYSCTLFN_PROTO); static int sysctl_kern_autonice(SYSCTLFN_PROTO); @@ -135,7 +137,6 @@ static int sysctl_kern_sbmax(SYSCTLFN_PROTO); static int sysctl_kern_urnd(SYSCTLFN_PROTO); static int sysctl_kern_lwp(SYSCTLFN_PROTO); -static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO); static int sysctl_kern_root_partition(SYSCTLFN_PROTO); static int sysctl_kern_drivers(SYSCTLFN_PROTO); static int sysctl_kern_file2(SYSCTLFN_PROTO); @@ -143,11 +144,13 @@ static int sysctl_kern_veriexec(SYSCTLFN_PROTO); #endif static int sysctl_doeproc(SYSCTLFN_PROTO); +static int sysctl_doeinst(SYSCTLFN_PROTO); static int sysctl_kern_proc_args(SYSCTLFN_PROTO); static int sysctl_hw_usermem(SYSCTLFN_PROTO); static int sysctl_hw_cnmagic(SYSCTLFN_PROTO); static int sysctl_hw_ncpu(SYSCTLFN_PROTO); +static void fill_inst(struct inst *, struct kinfo_inst *); static void fill_kproc2(struct proc *, struct kinfo_proc2 *); static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl); static void fill_file(struct kinfo_file *, const struct file *, struct proc *, @@ -320,7 +323,7 @@ CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "hostname", SYSCTL_DESCR("System hostname"), - sysctl_setlen, 0, &hostname, MAXHOSTNAMELEN, + sysctl_kern_hostname, 0, NULL, MAXHOSTNAMELEN, CTL_KERN, KERN_HOSTNAME, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_HEX, @@ -396,7 +399,7 @@ CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "domainname", SYSCTL_DESCR("YP domain name"), - sysctl_setlen, 0, &domainname, MAXHOSTNAMELEN, + sysctl_kern_hostname, 0, NULL, MAXHOSTNAMELEN, CTL_KERN, KERN_DOMAINNAME, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, @@ -645,12 +648,11 @@ sysctl_kern_lwp, 0, NULL, 0, CTL_KERN, KERN_LWP, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READWRITE, - CTLTYPE_INT, "forkfsleep", - SYSCTL_DESCR("Milliseconds to sleep on fork failure due " - "to process limits"), - sysctl_kern_forkfsleep, 0, NULL, 0, - CTL_KERN, KERN_FORKFSLEEP, CTL_EOL); + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "lwp_inst", + SYSCTL_DESCR("Instance LWP information"), + sysctl_kern_lwp, 0, NULL, 0, + CTL_KERN, KERN_LWP_INST, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, CTLTYPE_INT, "posix_threads", @@ -769,6 +771,20 @@ #endif /* VERIFIED_EXEC */ } +SYSCTL_SETUP(sysctl_kern_inst_setup, + "system kern.inst subtree setup") +{ + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL, + NULL, 0, NULL, 0, CTL_KERN, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "inst", + SYSCTL_DESCR("System-wide instance information"), + sysctl_doeinst, 0, NULL, 0, + CTL_KERN, KERN_INST, CTL_EOL); +} + + SYSCTL_SETUP(sysctl_kern_proc_setup, "sysctl kern.proc/proc2/proc_args subtree setup") { @@ -787,6 +803,12 @@ CTL_KERN, KERN_PROC, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, + CTLTYPE_NODE, "proc2_inst", + SYSCTL_DESCR("Instance-wide process information"), + sysctl_doeproc, 0, NULL, 0, + CTL_KERN, KERN_PROC2_INST, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "proc2", SYSCTL_DESCR("Machine-independent process information"), sysctl_doeproc, 0, NULL, 0, @@ -797,24 +819,15 @@ SYSCTL_DESCR("Process argument information"), sysctl_kern_proc_args, 0, NULL, 0, CTL_KERN, KERN_PROC_ARGS, CTL_EOL); - - /* - "nodes" under these: - - KERN_PROC_ALL - KERN_PROC_PID pid - KERN_PROC_PGRP pgrp - KERN_PROC_SESSION sess - KERN_PROC_TTY tty - KERN_PROC_UID uid - KERN_PROC_RUID uid - KERN_PROC_GID gid - KERN_PROC_RGID gid - - all in all, probably not worth the effort... - */ + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "proc_args_inst", + SYSCTL_DESCR("Instance process argument information"), + sysctl_kern_proc_args, 0, NULL, 0, + CTL_KERN, KERN_PROC_ARGS_INST, CTL_EOL); } + SYSCTL_SETUP(sysctl_hw_setup, "sysctl hw subtree setup") { u_int u; @@ -1142,32 +1155,40 @@ return (0); } + /* - * sysctl helper function for kern.hostname and kern.domainnname. - * resets the relevant recorded length when the underlying name is - * changed. + * Helper for kern.hostname. Returns the hostname associated with the + * LWP's instance. */ static int -sysctl_setlen(SYSCTLFN_ARGS) +sysctl_kern_hostname(SYSCTLFN_ARGS) { - int error; + int error; + char buf[MAXHOSTNAMELEN]; + struct sysctlnode node; - error = sysctl_lookup(SYSCTLFN_CALL(rnode)); - if (error || newp == NULL) - return (error); + buf[0] = 0; - switch (rnode->sysctl_num) { - case KERN_HOSTNAME: - hostnamelen = strlen((const char*)rnode->sysctl_data); - break; - case KERN_DOMAINNAME: - domainnamelen = strlen((const char*)rnode->sysctl_data); - break; + if (oldp) { + if (KERN_HOSTNAME == rnode->sysctl_num) + inst_get_hostname(l, buf, *oldlenp); + else + inst_get_domainname(l, buf, *oldlenp); } - return (0); + node = *rnode; + node.sysctl_data = &buf[0]; + + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || NULL == newp) + return(error); + + if (KERN_HOSTNAME == rnode->sysctl_num) + return (inst_set_hostname(l, buf)); + return (inst_set_domainname(l, buf)); } + /* * sysctl helper routine for kern.clockrate. assembles a struct on * the fly to be returned to the caller. @@ -1196,10 +1217,14 @@ static int sysctl_kern_file(SYSCTLFN_ARGS) { - int error; - size_t buflen; - struct file *fp; - char *start, *where; + int error; + size_t buflen; + struct file *fp; + char *start, *where; + + KASSERT(l); + KASSERT(l->l_proc); + KASSERT(l->l_inst); start = where = oldp; buflen = *oldlenp; @@ -1207,27 +1232,29 @@ /* * overestimate by 10 files */ - *oldlenp = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); + *oldlenp = sizeof(l->l_inst->i_filehead) + + (l->l_inst->i_nfiles + 10) * sizeof(struct file); return (0); } /* * first copyout filehead */ - if (buflen < sizeof(filehead)) { + if (buflen < sizeof(l->l_inst->i_filehead)) { *oldlenp = 0; return (0); } - error = copyout(&filehead, where, sizeof(filehead)); + error = copyout(&l->l_inst->i_filehead, + where, sizeof(l->l_inst->i_filehead)); if (error) return (error); - buflen -= sizeof(filehead); - where += sizeof(filehead); + buflen -= sizeof(l->l_inst->i_filehead); + where += sizeof(l->l_inst->i_filehead); /* * followed by an array of file structures */ - LIST_FOREACH(fp, &filehead, f_list) { + LIST_FOREACH(fp, &l->l_inst->i_filehead, f_list) { if (buflen < sizeof(struct file)) { *oldlenp = where - start; return (ENOMEM); @@ -1745,11 +1772,13 @@ sysctl_kern_lwp(SYSCTLFN_ARGS) { struct kinfo_lwp klwp; - struct proc *p; - struct lwp *l2; - char *where, *dp; - int pid, elem_size, elem_count; - int buflen, needed, error; + struct proc *p; + struct lwp *l2; + char *where, *dp; + int pid, elem_size, elem_count, + buflen, needed, error; + u_int uuid; + struct inst *i; if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); @@ -1758,15 +1787,33 @@ buflen = where != NULL ? *oldlenp : 0; error = needed = 0; - if (newp != NULL || namelen != 3) + if (newp != NULL) return (EINVAL); - pid = name[0]; - elem_size = name[1]; - elem_count = name[2]; - p = pfind(pid); - if (p == NULL) + if (KERN_LWP == rnode->sysctl_num) { + if (namelen != 3) + return (EINVAL); + pid = name[0]; + uuid = l->l_inst->i_uuid; + elem_size = name[1]; + elem_count = name[2]; + } else { + if (namelen != 4) + return (EINVAL); + uuid = (u_int)name[0]; + pid = name[1]; + elem_size = name[2]; + elem_count = name[3]; + } + + if (NULL == (i = inst_lookup(uuid))) return (ESRCH); + + if (NULL == (p = pfind(i, pid))) { + inst_release(i); + return (ESRCH); + } + LIST_FOREACH(l2, &p->p_lwps, l_sibling) { if (buflen >= elem_size && elem_count > 0) { fill_lwp(l2, &klwp); @@ -1784,6 +1831,7 @@ } needed += elem_size; } + inst_release(i); if (where != NULL) { *oldlenp = dp - where; @@ -1794,44 +1842,12 @@ *oldlenp = needed; } return (0); + cleanup: + inst_release(i); return (error); } -/* - * sysctl helper routine for kern.forkfsleep node. ensures that the - * given value is not too large or two small, and is at least one - * timer tick if not zero. - */ -static int -sysctl_kern_forkfsleep(SYSCTLFN_ARGS) -{ - /* userland sees value in ms, internally is in ticks */ - extern int forkfsleep; /* defined in kern/kern_fork.c */ - int error, timo, lsleep; - struct sysctlnode node; - - lsleep = forkfsleep * 1000 / hz; - node = *rnode; - node.sysctl_data = &lsleep; - error = sysctl_lookup(SYSCTLFN_CALL(&node)); - if (error || newp == NULL) - return (error); - - /* refuse negative values, and overly 'long time' */ - if (lsleep < 0 || lsleep > MAXSLP * 1000) - return (EINVAL); - - timo = mstohz(lsleep); - - /* if the interval is >0 ms && <1 tick, use 1 tick */ - if (lsleep != 0 && timo == 0) - forkfsleep = 1; - else - forkfsleep = timo; - - return (0); -} /* * sysctl helper routine for kern.root_partition @@ -1846,6 +1862,7 @@ return (sysctl_lookup(SYSCTLFN_CALL(&node))); } + /* * sysctl helper function for kern.drivers */ @@ -1903,14 +1920,18 @@ static int sysctl_kern_file2(SYSCTLFN_ARGS) { - struct proc *p; - struct file *fp; + struct proc *p; + struct file *fp; struct filedesc *fd; struct kinfo_file kf; - char *dp; - u_int i, op; - size_t len, needed, elem_size, out_size; - int error, arg, elem_count; + char *dp; + u_int i, op; + size_t len, needed, elem_size, out_size; + int error, arg, elem_count; + + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_inst); if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); @@ -1938,7 +1959,7 @@ */ if (arg != 0) return (EINVAL); - LIST_FOREACH(fp, &filehead, f_list) { + LIST_FOREACH(fp, &l->l_inst->i_filehead, f_list) { if (len >= elem_size && elem_count > 0) { fill_file(&kf, fp, NULL, 0); error = copyout(&kf, dp, out_size); @@ -1958,8 +1979,8 @@ if (arg < -1) /* -1 means all processes */ return (EINVAL); - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + proclist_lock_read(l->l_inst); + PROCLIST_FOREACH(p, &l->l_inst->i_allproc) { if (p->p_stat == SIDL) /* skip embryonic processes */ continue; @@ -1988,7 +2009,7 @@ } } } - proclist_unlock_read(); + proclist_unlock_read(l->l_inst); break; default: return (EINVAL); @@ -2040,29 +2061,112 @@ } } + +static int +sysctl_doeinst(SYSCTLFN_ARGS) +{ + struct kinfo_inst ui; + struct inst *i; + char *where, *dp2; + int op; + u_int elem_size, elem_count; + size_t buflen, needed; + int error; + + KASSERT(NULL != l); + KASSERT(NULL != l->l_inst); + + if (namelen == 1 && name[0] == CTL_QUERY) + return (sysctl_query(SYSCTLFN_CALL(rnode))); + + dp2 = where = oldp; + buflen = where != NULL ? *oldlenp : 0; + error = 0; + needed = 0; + + if (3 != namelen) + return(EINVAL); + + op = name[0]; + elem_size = name[1]; + elem_count = name[2]; + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + switch (op) { + case (KERN_INST_CUR): + if (i->i_uuid != l->l_inst->i_uuid) + continue; + break; + case (KERN_INST_ALL): + break; + default: + error = EINVAL; + goto cleanup; + } + if (buflen >= elem_size && elem_count > 0) { + fill_inst(i, &ui); + error = copyout(&ui, dp2, + min(sizeof(ui), elem_size)); + if (error) + goto cleanup; + dp2 += elem_size; + buflen -= elem_size; + elem_count--; + } + needed += elem_size; + if (KERN_INST_CUR == op) + /* We don't need any more. */ + break; + } + instlist_unlock_read(); + + if (where != NULL) { + *oldlenp = dp2 - where; + if (needed > *oldlenp) + return(ENOMEM); + } else { + needed += KERN_INSTSLOP; + *oldlenp = needed; + } + return(0); + + cleanup: + instlist_unlock_read(); + return(error); +} + + static int sysctl_doeproc(SYSCTLFN_ARGS) { - struct eproc eproc; + struct eproc eproc; struct kinfo_proc2 kproc2; struct kinfo_proc *dp; - struct proc *p; + struct proc *p; const struct proclist_desc *pd; - char *where, *dp2; - int type, op, arg; - u_int elem_size, elem_count; - size_t buflen, needed; - int error; + char *where, *dp2; + struct inst *i; + int type, op, arg; + u_int elem_size, elem_count, uuid; + size_t buflen, needed; + int error; + + KASSERT(l); + KASSERT(l->l_proc); + KASSERT(l->l_inst); if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); + i = NULL; dp = oldp; dp2 = where = oldp; buflen = where != NULL ? *oldlenp : 0; error = 0; needed = 0; type = rnode->sysctl_num; + uuid = l->l_inst->i_uuid; if (type == KERN_PROC) { if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) @@ -2073,6 +2177,14 @@ else arg = 0; /* Quell compiler warning */ elem_size = elem_count = 0; /* Ditto */ + } else if (type == KERN_PROC2_INST) { + if (namelen != 5) + return (EINVAL); + uuid = (u_int)name[0]; + op = name[1]; + arg = name[2]; + elem_size = name[3]; + elem_count = name[4]; } else { if (namelen != 4) return (EINVAL); @@ -2082,9 +2194,16 @@ elem_count = name[3]; } - proclist_lock_read(); + if (NULL == (i = inst_lookup(uuid))) + return (ESRCH); + if (INST_RUNNING != i->i_state) { + inst_release(i); + return (ESRCH); + } + + proclist_lock_read(i); + pd = i->i_proclists; - pd = proclists; again: PROCLIST_FOREACH(p, pd->pd_list) { /* @@ -2193,7 +2312,9 @@ pd++; if (pd->pd_list != NULL) goto again; - proclist_unlock_read(); + + proclist_unlock_read(i); + inst_release(i); if (where != NULL) { if (type == KERN_PROC) @@ -2207,8 +2328,13 @@ *oldlenp = needed; } return (0); + cleanup: - proclist_unlock_read(); + + KASSERT(i); + proclist_unlock_read(i); + inst_release(i); + return (error); } @@ -2226,16 +2352,29 @@ vaddr_t argv; pid_t pid; int nargv, type, error; - char *arg; - char *tmp; + char *arg, *tmp; + u_int uuid; + struct inst *inst; if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); - if (newp != NULL || namelen != 2) + if (newp != NULL) return (EINVAL); - pid = name[0]; - type = name[1]; + + if (KERN_PROC_ARGS == rnode->sysctl_num) { + if (namelen != 2) + return (EINVAL); + uuid = l->l_inst->i_uuid; + pid = name[0]; + type = name[1]; + } else { + if (namelen != 3) + return (EINVAL); + uuid = (u_int)name[0]; + pid = name[1]; + type = name[2]; + } switch (type) { case KERN_PROC_ARGV: @@ -2249,15 +2388,24 @@ } /* check pid */ - if ((p = pfind(pid)) == NULL) + + if (NULL == (inst = inst_lookup(uuid))) { return (EINVAL); + } + + if ((p = pfind(inst, pid)) == NULL) { + inst_release(inst); + return (EINVAL); + } /* only root or same user change look at the environment */ if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) { if (up->p_ucred->cr_uid != 0) { if (up->p_cred->p_ruid != p->p_cred->p_ruid || - up->p_cred->p_ruid != p->p_cred->p_svuid) + up->p_cred->p_ruid != p->p_cred->p_svuid) { + inst_release(inst); return (EPERM); + } } } @@ -2266,6 +2414,7 @@ *oldlenp = sizeof (int); else *oldlenp = ARG_MAX; /* XXX XXX XXX */ + inst_release(inst); return (0); } @@ -2273,15 +2422,19 @@ * Zombies don't have a stack, so we can't read their psstrings. * System processes also don't have a user stack. */ - if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) + if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) { + inst_release(inst); return (EINVAL); + } /* * Lock the process down in memory. */ /* XXXCDC: how should locking work here? */ - if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) + if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) { + inst_release(inst); return (EFAULT); + } p->p_vmspace->vm_refcnt++; /* XXX */ @@ -2303,8 +2456,9 @@ auio.uio_rw = UIO_READ; auio.uio_procp = NULL; error = uvm_io(&p->p_vmspace->vm_map, &auio); - if (error) + if (error){ goto done; + } if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv)); @@ -2327,6 +2481,7 @@ memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp)); break; default: + inst_release(inst); return (EINVAL); } auio.uio_offset = (off_t)(unsigned long)tmp; @@ -2389,8 +2544,8 @@ done: uvmspace_free(p->p_vmspace); - free(arg, M_TEMP); + inst_release(inst); return (error); } @@ -2582,10 +2737,7 @@ ki->p_flag = p->p_flag; ki->p_pid = p->p_pid; - if (p->p_pptr) - ki->p_ppid = p->p_pptr->p_pid; - else - ki->p_ppid = 0; + ki->p_ppid = p->p_pptr ? p->p_pptr->p_pid : 0; ki->p_sid = p->p_session->s_sid; ki->p__pgid = p->p_pgrp->pg_id; @@ -2768,6 +2920,29 @@ kl->l_cpuid = KI_NOCPU; } +void +fill_inst(struct inst *i, struct kinfo_inst *ui) +{ + KASSERT(NULL != i); + KASSERT(NULL != ui); + + simple_lock(&i->i_lock); + ui->i_uuid = i->i_uuid; + ui->i_refcnt = i->i_refcnt; + ui->i_state = (u_int32_t)i->i_state; + + strlcpy(ui->i_host, i->i_host, MAXHOSTNAMELEN); + strlcpy(ui->i_domain, i->i_domain, MAXHOSTNAMELEN); + simple_unlock(&i->i_lock); + + ui->i_ncreds = i->i_ncreds; + ui->i_nprocs = i->i_nprocs; + ui->i_nsess = i->i_nsess; + ui->i_nfiles = i->i_nfiles; + ui->i_npipes = i->i_npipes; + ui->i_nsocks = i->i_nsocks; +} + /* * Fill in an eproc structure for the specified process. */ @@ -2801,10 +2976,8 @@ if (l->l_wmesg) strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN); } - if (p->p_pptr) - ep->e_ppid = p->p_pptr->p_pid; - else - ep->e_ppid = 0; + + ep->e_ppid = p->p_pptr ? p->p_pptr->p_pid : 0; ep->e_pgid = p->p_pgrp->pg_id; ep->e_sid = ep->e_sess->s_sid; ep->e_jobc = p->p_pgrp->pg_jobc; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/init_sysent.c mult-netbsd-3.1/sys/kern/init_sysent.c --- NetBSD-3.1/sys/kern/init_sysent.c 2005-02-27 00:02:40.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/init_sysent.c 2007-11-15 13:34:52.000000000 +0000 @@ -1,4 +1,4 @@ -/* $NetBSD: init_sysent.c,v 1.163 2005/02/27 00:02:40 perry Exp $ */ +/* $NetBSD$ */ /* * System call switch table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: init_sysent.c,v 1.163 2005/02/27 00:02:40 perry Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #include "opt_ktrace.h" #include "opt_nfsserver.h" @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef COMPAT_43 #define compat_43(func) __CONCAT(compat_43_,func) @@ -994,8 +995,8 @@ sys_pselect }, /* 373 = pselect */ { 4, s(struct sys_pollts_args), 0, sys_pollts }, /* 374 = pollts */ - { 0, 0, 0, - sys_nosys }, /* 375 = filler */ + { 1, s(struct sys_instctl_args), 0, + sys_instctl }, /* 375 = instctl */ { 0, 0, 0, sys_nosys }, /* 376 = filler */ { 0, 0, 0, diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_acct.c mult-netbsd-3.1/sys/kern/kern_acct.c --- NetBSD-3.1/sys/kern/kern_acct.c 2004-12-13 08:46:43.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_acct.c 2007-11-26 15:42:56.000000000 +0000 @@ -1,4 +1,6 @@ -/* $NetBSD: kern_acct.c,v 1.60 2004/12/13 08:46:43 yamt Exp $ */ +/* $Id: kern_acct.c,v 1.8 2007/11/26 15:42:56 kristaps Exp $ */ + +/* $NetBSD: kern_acct.c,v 1.60 2004/12/13 08:46:43 yamt Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -94,117 +96,184 @@ #include #include +#include + + +enum acct_st_t +{ + ACCT_STOP, + ACCT_ACTIVE, + ACCT_SUSPENDED +}; + +struct inst_acct +{ + enum acct_st_t acct_state; /* Current account state. */ + struct vnode *acct_vp; /* Current vnode pointer. */ + struct ucred *acct_ucred; /* Account-file owner. */ + struct lock acct_lock; /* Serialise access. */ +}; + + +/* + * These refer to global resources: the dkwatcher. + */ + +struct proc *acct_dkwatcher; /* Free discspace checker. */ +struct lock acct_lock; /* Serialise access. */ + + +void +acct_init(void) +{ + lockinit(&acct_lock, PWAIT, "acctglk", 0, 0); + acct_dkwatcher = NULL; +} + + +int +inst_acct_alloc(inst_acct_t *p, int flags) +{ + struct inst_acct *i; + + KASSERT(p); + i = malloc(sizeof(struct inst_acct), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_acct)); + + i->acct_state = ACCT_STOP; + i->acct_vp = NULLVP; + i->acct_ucred = NULL; + lockinit(&i->acct_lock, PWAIT, "acctlk", 0, 0); + + *p = i; + return(1); +} + +void +inst_acct_free(inst_acct_t p) +{ + KASSERT(p); + free(p, M_INST); +} + + /* * The routines implemented in this file are described in: * Leffler, et al.: The Design and Implementation of the 4.3BSD * UNIX Operating System (Addison Welley, 1989) * on pages 62-63. * - * Arguably, to simplify accounting operations, this mechanism should - * be replaced by one in which an accounting log file (similar to /dev/klog) - * is read by a user process, etc. However, that has its own problems. + * Arguably, to simplify accounting operations, this mechanism should be + * replaced by one in which an accounting log file (similar to + * /dev/klog) is read by a user process, etc. However, that has its own + * problems. + * + * A significant amount of this was re-written to support multiple + * instance contexts. */ -/* - * The global accounting state and related data. Gain the lock before - * accessing these variables. - */ -enum { - ACCT_STOP, - ACCT_ACTIVE, - ACCT_SUSPENDED -} acct_state; /* The current accounting state. */ -struct vnode *acct_vp; /* Accounting vnode pointer. */ -struct ucred *acct_ucred; /* Credential of accounting file - owner (i.e root). Used when - accounting file i/o. */ -struct proc *acct_dkwatcher; /* Free disk space checker. */ +#define ACCT_LOCK(p) \ +do { \ + (void) lockmgr(&(p)->acct_lock, LK_EXCLUSIVE, NULL); \ +} while (/* CONSTCOND */0) -/* - * Lock to serialize system calls and kernel threads. - */ -struct lock acct_lock; -#define ACCT_LOCK() \ +#define ACCT_GLOBAL_LOCK() \ do { \ (void) lockmgr(&acct_lock, LK_EXCLUSIVE, NULL); \ } while (/* CONSTCOND */0) -#define ACCT_UNLOCK() \ + +#define ACCT_UNLOCK(p) \ +do { \ + (void) lockmgr(&(p)->acct_lock, LK_RELEASE, NULL); \ +} while (/* CONSTCOND */0) + +#define ACCT_GLOBAL_UNLOCK() \ do { \ (void) lockmgr(&acct_lock, LK_RELEASE, NULL); \ } while (/* CONSTCOND */0) + /* - * Internal accounting functions. - * The former's operation is described in Leffler, et al., and the latter - * was provided by UCB with the 4.4BSD-Lite release - */ -comp_t encode_comp_t(u_long, u_long); -void acctwatch(void *); -void acct_stop(void); -int acct_chkfree(void); + * Internal accounting functions. The former's operation is described + * in Leffler, et al., and the latter was provided by UCB with the + * 4.4BSD-Lite release. + */ +static comp_t encode_comp_t(u_long, u_long); +static int acct_chkfree(struct inst_acct *, int *); +static void acct_stop(struct inst_acct *); /* - * Values associated with enabling and disabling accounting + * Kernel-thread started to watch accounts. + */ +void acctwatch(void *); + +/* + * Values associated with enabling and disabling accounting. Note that + * these don't change, so we're free to leave them as they are. If they + * do change, we must put them in the instance. */ int acctsuspend = 2; /* stop accounting when < 2% free space left */ int acctresume = 4; /* resume when free space risen to > 4% */ int acctchkfreq = 15; /* frequency (in seconds) to check space */ -void -acct_init() -{ - - acct_state = ACCT_STOP; - acct_vp = NULLVP; - acct_ucred = NULL; - lockinit(&acct_lock, PWAIT, "acctlk", 0, 0); -} -void -acct_stop() +static void +acct_stop(struct inst_acct *p) { - int error; + int error; + + KASSERT(p); - if (acct_vp != NULLVP && acct_vp->v_type != VBAD) { - error = vn_close(acct_vp, FWRITE, acct_ucred, NULL); + if (p->acct_vp != NULLVP && p->acct_vp->v_type != VBAD) { + error = vn_close(p->acct_vp, FWRITE, + p->acct_ucred, NULL); #ifdef DIAGNOSTIC - if (error != 0) + if (0 != error) printf("acct_stop: failed to close, errno = %d\n", - error); + error); #endif - acct_vp = NULLVP; + p->acct_vp = NULLVP; } - if (acct_ucred != NULL) { - crfree(acct_ucred); - acct_ucred = NULL; + if (NULL != p->acct_ucred) { + crfree(p->acct_ucred); + p->acct_ucred = NULL; } - acct_state = ACCT_STOP; + p->acct_state = ACCT_STOP; } -int -acct_chkfree() + +static int +acct_chkfree(struct inst_acct *a, int *p) { - int error; - struct statvfs sb; - int64_t bavail; + int error; + struct statvfs sb; + int64_t bavail; + + KASSERT(a); - error = VFS_STATVFS(acct_vp->v_mount, &sb, NULL); + error = VFS_STATVFS(a->acct_vp->v_mount, &sb, NULL); if (error != 0) return (error); bavail = sb.f_bfree - sb.f_bresvd; - switch (acct_state) { + switch (a->acct_state) { case ACCT_SUSPENDED: + if (p) + (*p)++; if (bavail > acctresume * sb.f_blocks / 100) { - acct_state = ACCT_ACTIVE; - log(LOG_NOTICE, "Accounting resumed\n"); + a->acct_state = ACCT_ACTIVE; + log(LOG_NOTICE, "accounting resumed\n"); } break; case ACCT_ACTIVE: + if (p) + (*p)++; if (bavail <= acctsuspend * sb.f_blocks / 100) { - acct_state = ACCT_SUSPENDED; - log(LOG_NOTICE, "Accounting suspended\n"); + a->acct_state = ACCT_SUSPENDED; + log(LOG_NOTICE, "accounting suspended\n"); } break; case ACCT_STOP: @@ -213,22 +282,24 @@ return (0); } + /* * Accounting system call. Written based on the specification and * previous implementation done by Mark Tinguely. */ int -sys_acct(l, v, retval) - struct lwp *l; - void *v; - register_t *retval; +sys_acct(struct lwp *l, void *v, register_t *retval) { struct sys_acct_args /* { syscallarg(const char *) path; } */ *uap = v; struct nameidata nd; - int error; - struct proc *p = l->l_proc; + struct inst_acct *a; + int error; + struct proc *p; + + p = l->l_proc; + a = p->p_inst->i_acct; /* Make sure that the caller is root. */ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) @@ -258,7 +329,7 @@ if ((pad = (va.va_size % sizeof(struct acct))) != 0) { u_quad_t size = va.va_size - pad; #ifdef DIAGNOSTIC - printf("Size of accounting file not a multiple of " + printf("size of accounting file not a multiple of " "%lu - incomplete record truncated\n", (unsigned long)sizeof(struct acct)); #endif @@ -273,73 +344,86 @@ VOP_UNLOCK(nd.ni_vp, 0); } - ACCT_LOCK(); + ACCT_LOCK(a); /* - * If accounting was previously enabled, kill the old space-watcher, - * free credential for accounting file i/o, - * ... (and, if no new file was specified, leave). + * If accounting was previously enabled, kill the old + * space-watcher, free credential for accounting file i/o, ... + * (and, if no new file was specified, leave). */ - acct_stop(); + acct_stop(a); if (SCARG(uap, path) == NULL) goto out; /* - * Save the new accounting file vnode and credential, - * and schedule the new free space watcher. + * Save the new accounting file vnode and credential, and + * schedule the new free space watcher. */ - acct_state = ACCT_ACTIVE; - acct_vp = nd.ni_vp; - acct_ucred = p->p_ucred; - crhold(acct_ucred); + a->acct_state = ACCT_ACTIVE; + a->acct_vp = nd.ni_vp; + a->acct_ucred = p->p_ucred; + crhold(a->acct_ucred); + inst_hold(p->p_inst); - error = acct_chkfree(); /* Initial guess. */ + error = acct_chkfree(a, NULL); if (error != 0) { - acct_stop(); + acct_stop(a); goto out; } + ACCT_GLOBAL_LOCK(); if (acct_dkwatcher == NULL) { - error = kthread_create1(acctwatch, NULL, &acct_dkwatcher, - "acctwatch"); - if (error != 0) - acct_stop(); + error = kthread_create1(acctwatch, NULL, + &acct_dkwatcher, "acctwatch"); + if (error != 0) { + acct_stop(a); + inst_release(p->p_inst); + } } + ACCT_GLOBAL_UNLOCK(); out: - ACCT_UNLOCK(); + ACCT_UNLOCK(a); return (error); + bad: vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); return error; } + /* - * Write out process accounting information, on process exit. - * Data to be written out is specified in Leffler, et al. - * and are enumerated below. (They're also noted in the system - * "acct.h" header file.) + * Write out process accounting information, on process exit. Data to + * be written out is specified in Leffler, et al. and are enumerated + * below. (They're also noted in the system "acct.h" header file.) */ int -acct_process(p) - struct proc *p; +acct_process(struct proc *p) { - struct acct acct; - struct rusage *r; - struct timeval ut, st, tmp; - int s, t, error = 0; - struct plimit *oplim = NULL; + struct acct acct; + struct rusage *r; + struct timeval ut, st, tmp; + int s, t, error; + struct plimit *oplim; + struct inst_acct *a; + + error = 0; + oplim = NULL; + + KASSERT(p); + KASSERT(p->p_inst); + KASSERT(p->p_inst->i_acct); + a = p->p_inst->i_acct; - ACCT_LOCK(); + ACCT_LOCK(a); /* If accounting isn't enabled, don't bother */ - if (acct_state != ACCT_ACTIVE) + if (a->acct_state != ACCT_ACTIVE) goto out; /* * Raise the file limit so that accounting can't be stopped by * the user. - * * XXX We should think about the CPU limit, too. */ if (p->p_limit->p_refcnt > 1) { @@ -395,12 +479,12 @@ /* * Now, just write the accounting information to the file. */ - VOP_LEASE(acct_vp, p, p->p_ucred, LEASE_WRITE); - error = vn_rdwr(UIO_WRITE, acct_vp, (caddr_t)&acct, + VOP_LEASE(a->acct_vp, p, p->p_ucred, LEASE_WRITE); + error = vn_rdwr(UIO_WRITE, a->acct_vp, (caddr_t)&acct, sizeof(acct), (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, - acct_ucred, NULL, NULL); + a->acct_ucred, NULL, NULL); if (error != 0) - log(LOG_ERR, "Accounting: write failed %d\n", error); + log(LOG_ERR, "accounting: write failed: %d\n", error); if (oplim) { limfree(p->p_limit); @@ -408,25 +492,26 @@ } out: - ACCT_UNLOCK(); + ACCT_UNLOCK(a); return (error); } + /* - * Encode_comp_t converts from ticks in seconds and microseconds - * to ticks in 1/AHZ seconds. The encoding is described in - * Leffler, et al., on page 63. + * Encode_comp_t converts from ticks in seconds and microseconds to + * ticks in 1/AHZ seconds. The encoding is described in Leffler, et + * al., on page 63. */ #define MANTSIZE 13 /* 13 bit mantissa. */ #define EXPSIZE 3 /* Base 8 (3 bit) exponent. */ #define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */ -comp_t -encode_comp_t(s, us) - u_long s, us; + +static comp_t +encode_comp_t(u_long s, u_long us) { - int exp, rnd; + int exp, rnd; exp = 0; rnd = 0; @@ -451,44 +536,65 @@ return (exp); } + /* - * Periodically check the file system to see if accounting - * should be turned on or off. Beware the case where the vnode - * has been vgone()'d out from underneath us, e.g. when the file + * Kernel-thread to periodically check the file system to see if + * accounting should be turned on or off. Beware the case where the + * vnode has been vgone()'d out from underneath us, e.g. when the file * system containing the accounting file has been forcibly unmounted. + * Make sure, also, that the creating instance still exists. */ void -acctwatch(arg) - void *arg; +acctwatch(void *arg) { - int error; + int error, cnt; + struct inst *i; + struct inst_acct *a; - log(LOG_NOTICE, "Accounting started\n"); - ACCT_LOCK(); - while (acct_state != ACCT_STOP) { - if (acct_vp->v_type == VBAD) { - log(LOG_NOTICE, "Accounting terminated\n"); - acct_stop(); + log(LOG_NOTICE, "accounting started\n"); + +acctwatch_start: + + cnt = 0; + + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + a = i->i_acct; + KASSERT(a); + ACCT_LOCK(a); + + if (ACCT_STOP == a->acct_state) { + ACCT_UNLOCK(a); continue; } - error = acct_chkfree(); + if (a->acct_vp->v_type == VBAD) + acct_stop(a); + error = acct_chkfree(a, &cnt); #ifdef DIAGNOSTIC if (error != 0) printf("acctwatch: failed to statvfs, error = %d\n", - error); + error); #endif + ACCT_UNLOCK(a); + } + instlist_unlock_read(); - ACCT_UNLOCK(); + if (cnt > 0) { error = tsleep(acctwatch, PSWP, "actwat", acctchkfreq * hz); - ACCT_LOCK(); #ifdef DIAGNOSTIC if (error != 0 && error != EWOULDBLOCK) printf("acctwatch: sleep error %d\n", error); #endif + goto acctwatch_start; } + + log(LOG_NOTICE, "accounting terminated\n"); + + ACCT_GLOBAL_LOCK(); acct_dkwatcher = NULL; - ACCT_UNLOCK(); + ACCT_GLOBAL_UNLOCK(); kthread_exit(0); } + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_descrip.c mult-netbsd-3.1/sys/kern/kern_descrip.c --- NetBSD-3.1/sys/kern/kern_descrip.c 2005-05-28 13:41:08.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_descrip.c 2007-11-26 15:08:35.000000000 +0000 @@ -64,25 +64,24 @@ #include #include -/* - * Descriptor management. - */ -struct filelist filehead; /* head of list of open files */ -int nfiles; /* actual number of open files */ -POOL_INIT(file_pool, sizeof(struct file), 0, 0, 0, "filepl", - &pool_allocator_nointr); -POOL_INIT(cwdi_pool, sizeof(struct cwdinfo), 0, 0, 0, "cwdipl", - &pool_allocator_nointr); -POOL_INIT(filedesc0_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl", - &pool_allocator_nointr); +#include + + +static POOL_INIT(file_pool, sizeof(struct file), + 0, 0, 0, "filepl", &pool_allocator_nointr); + +static POOL_INIT(cwdi_pool, sizeof(struct cwdinfo), + 0, 0, 0, "cwdipl", &pool_allocator_nointr); + +static POOL_INIT(filedesc0_pool, sizeof(struct filedesc0), + 0, 0, 0, "fdescpl", &pool_allocator_nointr); -/* Global file list lock */ -static struct simplelock filelist_slock = SIMPLELOCK_INITIALIZER; MALLOC_DEFINE(M_FILE, "file", "Open file structure"); MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table"); MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer"); + static __inline void fd_used(struct filedesc *, int); static __inline void fd_unused(struct filedesc *, int); static __inline int find_next_zero(uint32_t *, int, u_int); @@ -90,13 +89,16 @@ int find_last_set(struct filedesc *, int); int fcntl_forfs(int, struct proc *, int, void *); + dev_type_open(filedescopen); + const struct cdevsw filedesc_cdevsw = { filedescopen, noclose, noread, nowrite, noioctl, nostop, notty, nopoll, nommap, nokqfilter, }; + static __inline int find_next_zero(uint32_t *bitmap, int want, u_int bits) { @@ -128,6 +130,7 @@ return (off << NDENTRYSHIFT) + ffs(~sub) - 1; } + int find_last_set(struct filedesc *fd, int last) { @@ -819,6 +822,7 @@ uint32_t *newhimap = NULL, *newlomap = NULL; fdp = p->p_fd; + KASSERT(NULL != p->p_inst); restart: oldnfiles = fdp->fd_nfiles; @@ -828,12 +832,14 @@ else nfiles = 2 * oldnfiles; - newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK); + newofile = malloc + (nfiles * OFILESIZE, M_FILEDESC, M_WAITOK); if (NDHISLOTS(nfiles) > NDHISLOTS(oldnfiles)) { newhimap = malloc(NDHISLOTS(nfiles) * sizeof(uint32_t), - M_FILEDESC, M_WAITOK); - newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(uint32_t), - M_FILEDESC, M_WAITOK); + M_FILEDESC, M_WAITOK); + newlomap = malloc(NDLOSLOTS + (nfiles) * sizeof(uint32_t), + M_FILEDESC, M_WAITOK); } simple_lock(&fdp->fd_slock); @@ -922,6 +928,8 @@ struct file *fp, *fq; int error, i; + KASSERT(p->p_inst); + restart: if ((error = fdalloc(p, 0, &i)) != 0) { if (error == ENOSPC) { @@ -932,10 +940,10 @@ } fp = pool_get(&file_pool, PR_WAITOK); - simple_lock(&filelist_slock); - if (nfiles >= maxfiles) { + simple_lock(&p->p_inst->i_filelist_lock); + if (p->p_inst->i_nfiles >= maxfiles) { tablefull("file", "increase kern.maxfiles or MAXFILES"); - simple_unlock(&filelist_slock); + simple_unlock(&p->p_inst->i_filelist_lock); fd_unused(p->p_fd, i); pool_put(&file_pool, fp); return (ENFILE); @@ -946,21 +954,22 @@ * of open files at that point, otherwise put it at the front of * the list of open files. */ - nfiles++; + p->p_inst->i_nfiles++; memset(fp, 0, sizeof(struct file)); fp->f_iflags = FIF_LARVAL; if ((fq = p->p_fd->fd_ofiles[0]) != NULL) { LIST_INSERT_AFTER(fq, fp, f_list); } else { - LIST_INSERT_HEAD(&filehead, fp, f_list); + LIST_INSERT_HEAD(&p->p_inst->i_filehead, fp, f_list); } - simple_unlock(&filelist_slock); + simple_unlock(&p->p_inst->i_filelist_lock); KDASSERT(p->p_fd->fd_ofiles[i] == NULL); p->p_fd->fd_ofiles[i] = fp; simple_lock_init(&fp->f_slock); fp->f_count = 1; fp->f_cred = p->p_ucred; crhold(fp->f_cred); + if (resultfp) { fp->f_usecount = 1; *resultfp = fp; @@ -976,23 +985,29 @@ void ffree(struct file *fp) { + struct inst *i; + + KASSERT(fp->f_cred->cr_inst); + i = fp->f_cred->cr_inst; #ifdef DIAGNOSTIC if (fp->f_usecount) panic("ffree"); #endif - simple_lock(&filelist_slock); + simple_lock(&i->i_filelist_lock); LIST_REMOVE(fp, f_list); + i->i_nfiles--; + simple_unlock(&i->i_filelist_lock); + crfree(fp->f_cred); #ifdef DIAGNOSTIC fp->f_count = 0; /* What's the point? */ #endif - nfiles--; - simple_unlock(&filelist_slock); pool_put(&file_pool, fp); } + /* * Create an initial cwdinfo structure, using the same current and root * directories as p. @@ -1074,18 +1089,17 @@ * directories as p. */ struct filedesc * -fdinit(struct proc *p) +fdinit(void) { struct filedesc0 *newfdp; newfdp = pool_get(&filedesc0_pool, PR_WAITOK); memset(newfdp, 0, sizeof(struct filedesc0)); - fdinit1(newfdp); - return (&newfdp->fd_fd); } + /* * Initialize a file descriptor table. */ @@ -1143,7 +1157,7 @@ { struct filedesc *newfd; - newfd = fdinit(p); + newfd = fdinit(); fdfree(p); p->p_fd = newfd; } @@ -1163,6 +1177,8 @@ newfdp->fd_refcnt = 1; simple_lock_init(&newfdp->fd_slock); + KASSERT(NULL != p->p_inst); + restart: nfiles = fdp->fd_nfiles; lastfile = fdp->fd_lastfile; @@ -1194,7 +1210,8 @@ } simple_lock(&fdp->fd_slock); - if (nfiles != fdp->fd_nfiles || lastfile != fdp->fd_lastfile) { + if (nfiles != fdp->fd_nfiles || + lastfile != fdp->fd_lastfile) { simple_unlock(&fdp->fd_slock); if (i > NDFILE) free(newfdp->fd_ofiles, M_FILEDESC); @@ -1766,10 +1783,13 @@ if (closed[0] != '\0') { pp = p->p_pptr; log(LOG_WARNING, "set{u,g}id pid %d (%s) " - "was invoked by uid %d ppid %d (%s) " - "with fd %s closed\n", - p->p_pid, p->p_comm, pp->p_ucred->cr_uid, - pp->p_pid, pp->p_comm, &closed[1]); + "was invoked by uid %d ppid %d (%s) " + "with fd %s closed\n", + p->p_pid, p->p_comm, + pp ? pp->p_ucred->cr_uid : 0, + pp ? pp->p_pid : 0, + pp ? pp->p_comm : "(null)", + &closed[1]); } return (0); } @@ -1796,7 +1816,7 @@ break; } - if (id > 0 && !pfind(id)) + if (id > 0 && ! pfind(p->p_inst, id)) return (ESRCH); else if (id < 0 && (error = pgid_in_session(p, -id))) return (error); @@ -1828,20 +1848,23 @@ * Send signal to descriptor owner, either process or process group. */ void -fownsignal(pid_t pgid, int signo, int code, int band, void *fdescdata) +fownsignal(struct inst *i, pid_t pgid, int signo, + int code, int band, void *fdescdata) { - struct proc *p1; - ksiginfo_t ksi; + struct proc *p1; + ksiginfo_t ksi; + + KASSERT(i); - memset(&ksi, 0, sizeof(ksi)); + (void)memset(&ksi, 0, sizeof(ksi)); ksi.ksi_signo = signo; ksi.ksi_code = code; ksi.ksi_band = band; - if (pgid > 0 && (p1 = pfind(pgid))) + if (pgid > 0 && (p1 = pfind(i, pgid))) kpsignal(p1, &ksi, fdescdata); else if (pgid < 0) - kgsignal(-pgid, &ksi, fdescdata); + kgsignal(i, -pgid, &ksi, fdescdata); } int diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_event.c mult-netbsd-3.1/sys/kern/kern_event.c --- NetBSD-3.1/sys/kern/kern_event.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_event.c 2007-11-26 15:08:35.000000000 +0000 @@ -53,6 +53,7 @@ #include #include #include +#include static int kqueue_scan(struct file *fp, size_t maxevents, struct kevent *ulistp, const struct timespec *timeout, @@ -146,10 +147,37 @@ { NULL, 0, NULL }, /* end of list */ }; - /* User defined kfilters */ -static struct kfilter *user_kfilters; /* array */ -static int user_kfilterc; /* current offset */ -static int user_kfiltermaxc; /* max size so far */ + +struct inst_kevt +{ + struct kfilter *user_kfilters; /* array */ + int user_kfilterc; /* current offset */ + int user_kfiltermaxc; /* max size thusfar */ +}; + + +int +inst_kevt_alloc(inst_kevt_t *p, int flags) +{ + struct inst_kevt *i; + + KASSERT(p); + i = malloc(sizeof(struct inst_kevt), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_kevt)); + *p = i; + return(1); +} + + +void +inst_kevt_free(inst_kevt_t p) +{ + KASSERT(p); + free(p, M_INST); +} + /* * Find kfilter entry by name, or NULL if not found. @@ -166,135 +194,157 @@ return (NULL); } + static struct kfilter * -kfilter_byname_user(const char *name) +kfilter_byname_user(struct inst_kevt *p, const char *name) { int i; + KASSERT(p); + /* user_kfilters[] could be NULL if no filters were registered */ - if (!user_kfilters) + if (!p->user_kfilters) return (NULL); - for (i = 0; user_kfilters[i].name != NULL; i++) { - if (user_kfilters[i].name != '\0' && - strcmp(name, user_kfilters[i].name) == 0) - return (&user_kfilters[i]); + for (i = 0; p->user_kfilters[i].name != NULL; i++) { + if (p->user_kfilters[i].name != '\0' && + strcmp(name, p->user_kfilters[i].name) == 0) + return (&p->user_kfilters[i]); } return (NULL); } + static const struct kfilter * -kfilter_byname(const char *name) +kfilter_byname(struct inst_kevt *p, const char *name) { const struct kfilter *kfilter; + KASSERT(p); + if ((kfilter = kfilter_byname_sys(name)) != NULL) return (kfilter); - return (kfilter_byname_user(name)); + return (kfilter_byname_user(p, name)); } + /* - * Find kfilter entry by filter id, or NULL if not found. - * Assumes entries are indexed in filter id order, for speed. + * Find kfilter entry by filter id, or NULL if not found. Assumes + * entries are indexed in filter id order, for speed. */ static const struct kfilter * -kfilter_byfilter(uint32_t filter) +kfilter_byfilter(struct inst_kevt *p, uint32_t filter) { const struct kfilter *kfilter; if (filter < EVFILT_SYSCOUNT) /* it's a system filter */ kfilter = &sys_kfilters[filter]; - else if (user_kfilters != NULL && - filter < EVFILT_SYSCOUNT + user_kfilterc) + else if (p->user_kfilters != NULL && + filter < EVFILT_SYSCOUNT + p->user_kfilterc) /* it's a user filter */ - kfilter = &user_kfilters[filter - EVFILT_SYSCOUNT]; + kfilter = &p->user_kfilters[filter - EVFILT_SYSCOUNT]; else return (NULL); /* out of range */ KASSERT(kfilter->filter == filter); /* sanity check! */ return (kfilter); } + /* * Register a new kfilter. Stores the entry in user_kfilters. * Returns 0 if operation succeeded, or an appropriate errno(2) otherwise. * If retfilter != NULL, the new filterid is returned in it. */ int -kfilter_register(const char *name, const struct filterops *filtops, - int *retfilter) +kfilter_register(struct inst *i, const char *name, + const struct filterops *filtops, int *retfilter) { - struct kfilter *kfilter; - void *space; - int len; + struct kfilter *kfilter; + void *space; + int len; + KASSERT(i); if (name == NULL || name[0] == '\0' || filtops == NULL) return (EINVAL); /* invalid args */ - if (kfilter_byname(name) != NULL) + if (kfilter_byname(i->i_kevt, name) != NULL) return (EEXIST); /* already exists */ - if (user_kfilterc > 0xffffffff - EVFILT_SYSCOUNT) + if (i->i_kevt->user_kfilterc > 0xffffffff - EVFILT_SYSCOUNT) return (EINVAL); /* too many */ /* check if need to grow user_kfilters */ - if (user_kfilterc + 1 > user_kfiltermaxc) { + if (i->i_kevt->user_kfilterc + 1 > + i->i_kevt->user_kfiltermaxc) { /* * Grow in KFILTER_EXTENT chunks. Use malloc(9), because we * want to traverse user_kfilters as an array. */ - user_kfiltermaxc += KFILTER_EXTENT; - kfilter = malloc(user_kfiltermaxc * sizeof(struct filter *), - M_KEVENT, M_WAITOK); + i->i_kevt->user_kfiltermaxc += KFILTER_EXTENT; + kfilter = malloc(i->i_kevt->user_kfiltermaxc * + sizeof(struct filter *), + M_KEVENT, M_WAITOK); /* copy existing user_kfilters */ - if (user_kfilters != NULL) - memcpy((caddr_t)kfilter, (caddr_t)user_kfilters, - user_kfilterc * sizeof(struct kfilter *)); + if (i->i_kevt->user_kfilters != NULL) + memcpy((caddr_t)kfilter, + (caddr_t)i->i_kevt->user_kfilters, + i->i_kevt->user_kfilterc * + sizeof(struct kfilter *)); /* zero new sections */ memset((caddr_t)kfilter + - user_kfilterc * sizeof(struct kfilter *), 0, - (user_kfiltermaxc - user_kfilterc) * - sizeof(struct kfilter *)); - /* switch to new kfilter */ - if (user_kfilters != NULL) - free(user_kfilters, M_KEVENT); - user_kfilters = kfilter; + i->i_kevt->user_kfilterc * + sizeof(struct kfilter *), 0, + (i->i_kevt->user_kfiltermaxc - + i->i_kevt->user_kfilterc) * + sizeof(struct kfilter *)); + /* switch to new kfilter */ + if (i->i_kevt->user_kfilters != NULL) + free(i->i_kevt->user_kfilters, M_KEVENT); + i->i_kevt->user_kfilters = kfilter; } len = strlen(name) + 1; /* copy name */ space = malloc(len, M_KEVENT, M_WAITOK); memcpy(space, name, len); - user_kfilters[user_kfilterc].name = space; + i->i_kevt->user_kfilters[i->i_kevt->user_kfilterc].name = + space; - user_kfilters[user_kfilterc].filter = user_kfilterc + EVFILT_SYSCOUNT; + i->i_kevt->user_kfilters[i->i_kevt->user_kfilterc].filter = + i->i_kevt->user_kfilterc + EVFILT_SYSCOUNT; len = sizeof(struct filterops); /* copy filtops */ space = malloc(len, M_KEVENT, M_WAITOK); memcpy(space, filtops, len); - user_kfilters[user_kfilterc].filtops = space; + i->i_kevt->user_kfilters[i->i_kevt->user_kfilterc].filtops = + space; if (retfilter != NULL) - *retfilter = user_kfilters[user_kfilterc].filter; - user_kfilterc++; /* finally, increment count */ + *retfilter = i->i_kevt->user_kfilters + [i->i_kevt->user_kfilterc].filter; + i->i_kevt->user_kfilterc++; + /* finally, increment count */ return (0); } + /* * Unregister a kfilter previously registered with kfilter_register. - * This retains the filter id, but clears the name and frees filtops (filter - * operations), so that the number isn't reused during a boot. - * Returns 0 if operation succeeded, or an appropriate errno(2) otherwise. + * This retains the filter id, but clears the name and frees filtops + * (filter operations), so that the number isn't reused during a boot. + * Returns 0 if operation succeeded, or an appropriate errno(2) + * otherwise. */ int -kfilter_unregister(const char *name) +kfilter_unregister(struct inst *i, const char *name) { - struct kfilter *kfilter; + struct kfilter *kfilter; - if (name == NULL || name[0] == '\0') + if (i == NULL || name == NULL || name[0] == '\0') return (EINVAL); /* invalid name */ if (kfilter_byname_sys(name) != NULL) return (EINVAL); /* can't detach system filters */ - kfilter = kfilter_byname_user(name); + kfilter = kfilter_byname_user(i->i_kevt, name); if (kfilter == NULL) /* not found */ return (ENOENT); @@ -359,7 +409,8 @@ { struct proc *p; - p = pfind(kn->kn_id); + /* FIXME - instances */ + p = pfind(NULL, kn->kn_id); if (p == NULL) return (ESRCH); @@ -409,7 +460,8 @@ return; p = kn->kn_ptr.p_proc; - KASSERT(p->p_stat == SZOMB || pfind(kn->kn_id) == p); + /* FIXME - instances */ + KASSERT(p->p_stat == SZOMB || pfind(NULL, kn->kn_id) == p); /* XXXSMP lock the process? */ SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext); @@ -730,11 +782,13 @@ struct knote *kn; int s, error; + KASSERT(NULL != p); + fdp = kq->kq_fdp; fp = NULL; kn = NULL; error = 0; - kfilter = kfilter_byfilter(kev->filter); + kfilter = kfilter_byfilter(p->p_inst->i_kevt, kev->filter); if (kfilter == NULL || kfilter->filtops == NULL) { /* filter not found nor implemented */ return (EINVAL); @@ -1073,9 +1127,11 @@ km = (struct kfilter_mapping *)data; error = 0; + KASSERT(p->p_inst); + switch (com) { case KFILTER_BYFILTER: /* convert filter -> name */ - kfilter = kfilter_byfilter(km->filter); + kfilter = kfilter_byfilter(p->p_inst->i_kevt, km->filter); if (kfilter != NULL) error = copyoutstr(kfilter->name, km->name, km->len, NULL); @@ -1090,7 +1146,7 @@ FREE(name, M_KEVENT); break; } - kfilter = kfilter_byname(name); + kfilter = kfilter_byname(p->p_inst->i_kevt, name); if (kfilter != NULL) km->filter = kfilter->filter; else diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_exec.c mult-netbsd-3.1/sys/kern/kern_exec.c --- NetBSD-3.1/sys/kern/kern_exec.c 2005-10-31 13:25:31.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_exec.c 2007-11-23 10:17:19.000000000 +0000 @@ -69,6 +69,7 @@ #endif #include +#include #include #include @@ -288,6 +289,7 @@ */ epp->ep_vm_minaddr = VM_MIN_ADDRESS; epp->ep_vm_maxaddr = VM_MAXUSER_ADDRESS; + /* * set up the vmcmds for creation of the process * address space @@ -712,6 +714,7 @@ p->p_flag |= P_EXEC; if (p->p_flag & P_PPWAIT) { + KASSERT(p->p_pptr); p->p_flag &= ~P_PPWAIT; wakeup((caddr_t) p->p_pptr); } @@ -832,6 +835,7 @@ int s; sigminusset(&contsigmask, &p->p_sigctx.ps_siglist); + KASSERT(p->p_pptr); SCHED_LOCK(s); p->p_pptr->p_nstopchild++; p->p_stat = SSTOP; @@ -996,6 +1000,7 @@ struct emul_entry *it; int i, error; struct proc *ptmp; + struct inst *inst; error = 0; lockmgr(&exec_lock, LK_SHARED, NULL); @@ -1028,16 +1033,23 @@ * emul_unregister() is running quite sendomly, it's better * to do expensive check here than to use any locking. */ - proclist_lock_read(); - for (pd = proclists; pd->pd_list != NULL && !error; pd++) { - PROCLIST_FOREACH(ptmp, pd->pd_list) { - if (ptmp->p_emul == it->el_emul) { - error = EBUSY; - break; + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) { + proclist_lock_read(inst); + for (pd = inst->i_proclists; + pd->pd_list != NULL && !error; pd++) { + PROCLIST_FOREACH(ptmp, pd->pd_list) { + if (ptmp->p_emul == it->el_emul) { + error = EBUSY; + break; + } } } + proclist_unlock_read(inst); + if (error) + break; } - proclist_unlock_read(); + instlist_unlock_read(); if (error) goto out; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_exit.c mult-netbsd-3.1/sys/kern/kern_exit.c --- NetBSD-3.1/sys/kern/kern_exit.c 2005-10-04 15:16:42.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_exit.c 2007-12-18 17:56:36.000000000 +0000 @@ -78,7 +78,6 @@ #include "opt_ktrace.h" #include "opt_perfctrs.h" -#include "opt_systrace.h" #include "opt_sysv.h" #include @@ -112,22 +111,18 @@ #include #include #include -#include +#include #include #include -#define DEBUG_EXIT +static POOL_INIT(rusage_pool, sizeof(struct rusage), + 0, 0, 0, "rusgepl", &pool_allocator_nointr); -#ifdef DEBUG_EXIT -int debug_exit = 0; -#define DPRINTF(x) if (debug_exit) printf x -#else -#define DPRINTF(x) -#endif +static void +lwp_exit_hook(struct lwp *, void *); -static void lwp_exit_hook(struct lwp *, void *); /* * Fill in the appropriate signal information, and signal the parent. @@ -178,6 +173,76 @@ return (0); } + +/* + * This is documented in exitinst1(9). + */ +static void +exitinst1(struct inst *i, int rv) +{ + int count, error; + struct inst *p; + ksiginfo_t ksi; + struct proc *child; + + KASSERT(i); + + count = 0; + instlist_lock_read(); + LIST_FOREACH(p, &allinst, i_list) + count++; + instlist_unlock_read(); + + KASSERT(count >= 2); + if (2 == count) + panic("init died (uuid %u, signal %d, exit %d)", + i->i_uuid, WTERMSIG(rv), WEXITSTATUS(rv)); + +#ifdef DEBUG + printf("%s: instance exiting: %u\n", __func__, i->i_uuid); +#endif + + i->i_state = INST_EXITING; + + /* + * Kill all members of the instance. This will eventually cause + * the tree to reparent under the instance. + */ + + KSI_INIT(&ksi); + ksi.ksi_signo = SIGKILL; + ksi.ksi_code = SI_NOINFO; + ksi.ksi_pid = 1; + ksi.ksi_uid = 0; + + (void)killpg1(i->i_initproc, &ksi, 0, 1); + + for (;;) { + error = find_stopped_child(i->i_initproc, WAIT_ANY, 0, &child); + if (ECHILD == error) { +#ifdef DEBUG + printf("%s: no more children: uuid %u\n", + __func__, i->i_uuid); +#endif + break; + } else if (EINTR == error || ERESTART == error) + continue; + /* What to do here? FIXME. */ + KASSERT(0 == error); + KASSERT(child); +#ifdef DEBUG + printf("%s: freeing child: %d, %u\n", + __func__, child->p_pid, i->i_uuid); +#endif + uvm_uarea_drain(FALSE); + proc_free(child); + } + + instdaemon_sem = 1; + wakeup((void *)&instdaemon_sem); +} + + /* * Exit: deallocate address space and other resources, change proc state * to zombie, and unlink proc from allproc and parent's lists. Save exit @@ -187,20 +252,24 @@ exit1(struct lwp *l, int rv) { struct proc *p, *q, *nq; + struct inst *inst; int s, sa; struct plimit *plim; struct pstats *pstats; struct sigacts *ps; ksiginfo_t ksi; - int do_psignal = 0; + int do_psignal; + do_psignal = 0; p = l->l_proc; - - if (__predict_false(p == initproc)) - panic("init died (signal %d, exit %d)", - WTERMSIG(rv), WEXITSTATUS(rv)); + KASSERT(l->l_inst); + inst = l->l_inst; p->p_flag |= P_WEXIT; + if (p == inst->i_initproc) + /* Note that instinit(8) is marked as exiting. */ + exitinst1(inst, rv); + if (p->p_flag & P_STOPEXIT) { int s; @@ -214,17 +283,13 @@ splx(s); } - DPRINTF(("exit1: %d.%d exiting.\n", p->p_pid, l->l_lid)); /* - * Disable scheduler activation upcalls. - * We're trying to get out of here. + * Disable scheduler activation upcalls. We're trying to get + * out of here. */ sa = 0; if (p->p_sa != NULL) { l->l_flag &= ~L_SA; -#if 0 - p->p_flag &= ~P_SA; -#endif sa = 1; } @@ -234,11 +299,13 @@ if (p->p_flag & P_PROFIL) stopprofclock(p); p->p_ru = pool_get(&rusage_pool, PR_WAITOK); + /* - * If parent is waiting for us to exit or exec, P_PPWAIT is set; we - * wake up the parent early to avoid deadlock. + * If parent is waiting for us to exit or exec, P_PPWAIT is set; + * we wake up the parent early to avoid deadlock. */ if (p->p_flag & P_PPWAIT) { + KASSERT(p->p_pptr); p->p_flag &= ~P_PPWAIT; wakeup(p->p_pptr); } @@ -249,7 +316,6 @@ if (sa || (p->p_nlwps > 1)) { exit_lwps(l); - /* * Collect thread u-areas. */ @@ -261,8 +327,8 @@ #endif /* - * Close open files and release open-file table. - * This may block! + * Close open files and release open-file table. This may + * block! */ fdfree(p); cwdfree(p->p_cwdi); @@ -277,10 +343,9 @@ if (sp->s_ttyvp) { int s; /* - * Controlling process. - * Signal foreground pgrp, - * drain controlling terminal - * and revoke access to controlling terminal. + * Controlling process. Signal foreground pgrp, + * drain controlling terminal and revoke access + * to controlling terminal. */ tp = sp->s_ttyp; s = spltty(); @@ -288,7 +353,8 @@ if (tp->t_session == sp) { if (tp->t_pgrp) pgsignal(tp->t_pgrp, SIGHUP, 1); - /* we can't guarantee the revoke will do this */ + /* We can't guarantee the revoke will do + * this. */ tp->t_pgrp = NULL; tp->t_session = NULL; TTY_UNLOCK(tp); @@ -296,8 +362,8 @@ SESSRELE(sp); (void) ttywait(tp); /* - * The tty could have been revoked - * if we blocked. + * The tty could have been revoked if we + * blocked. */ if (sp->s_ttyvp) VOP_REVOKE(sp->s_ttyvp, REVOKEALL); @@ -310,10 +376,11 @@ sp->s_ttyvp = NULL; /* * s_ttyp is not zero'd; we use this to indicate - * that the session once had a controlling terminal. - * (for logging and informational purposes) + * that the session once had a controlling + * terminal. (for logging and informational + * purposes) */ - } + } sp->s_leader = NULL; } fixjobc(p, p->p_pgrp, 0); @@ -324,9 +391,6 @@ */ ktrderef(p); #endif -#ifdef SYSTRACE - systrace_sys_exit(p); -#endif /* * If emulation has process exit hook, call it now. */ @@ -334,21 +398,19 @@ (*p->p_emul->e_proc_exit)(p); /* - * Free the VM resources we're still holding on to. - * We must do this from a valid thread because doing - * so may block. This frees vmspace, which we don't - * need anymore. The only remaining lwp is the one - * we run at this moment, nothing runs in userland - * anymore. + * Free the VM resources we're still holding on to. We must do + * this from a valid thread because doing so may block. This + * frees vmspace, which we don't need anymore. The only + * remaining lwp is the one we run at this moment, nothing runs + * in userland anymore. */ uvm_proc_exit(p); /* - * Give machine-dependent code a chance to free any - * MD LWP resources while we can still block. This must be done - * before uvm_lwp_exit(), in case these resources are in the - * PCB. - * THIS IS LAST BLOCKING OPERATION. + * Give machine-dependent code a chance to free any MD LWP + * resources while we can still block. This must be done before + * uvm_lwp_exit(), in case these resources are in the PCB. THIS + * IS LAST BLOCKING OPERATION. */ #ifndef __NO_CPU_LWP_FREE cpu_lwp_free(l, 1); @@ -361,10 +423,10 @@ */ /* - * Save exit status and final rusage info, adding in child rusage - * info and self times. - * In order to pick up the time for the current execution, we must - * do this before unlinking the lwp from l_list. + * Save exit status and final rusage info, adding in child + * rusage info and self times. In order to pick up the time for + * the current execution, we must do this before unlinking the + * lwp from l_list. */ p->p_xstat = rv; *p->p_ru = p->p_stats->p_ru; @@ -380,24 +442,24 @@ /* * Save final PMC information in parent process & clean up. */ - if (PMC_ENABLED(p)) { + if (PMC_ENABLED(p) && p->p_pptr) { pmc_save_context(p); pmc_accumulate(p->p_pptr, p); pmc_process_exit(p); } #endif - s = proclist_lock_write(); + s = proclist_lock_write(p->p_inst); + /* - * Reset p_opptr pointer of all former children which got - * traced by another process and were reparented. We reset - * it to NULL here; the trace detach code then reparents - * the child to initproc. We only check allproc list, since - * eventual former children on zombproc list won't reference - * p_opptr anymore. + * Reset p_opptr pointer of all former children which got traced + * by another process and were reparented. We reset it to NULL + * here; the trace detach code then reparents the child to + * initproc. We only check allproc list, since eventual former + * children on zombproc list won't reference p_opptr anymore. */ if (p->p_flag & P_CHTRACED) { - PROCLIST_FOREACH(q, &allproc) { + PROCLIST_FOREACH(q, &p->p_inst->i_allproc) { if (q->p_opptr == p) q->p_opptr = NULL; } @@ -408,7 +470,7 @@ */ q = LIST_FIRST(&p->p_children); if (q) /* only need this if any child is SZOMB */ - wakeup(initproc); + wakeup(inst->i_initproc); for (; q != NULL; q = nq) { nq = LIST_NEXT(q, p_sibling); @@ -420,28 +482,30 @@ * original parent, so we must do this here. */ if (q->p_flag & P_TRACED) { + KASSERT(q->p_pptr); if (q->p_opptr != q->p_pptr) { struct proc *t = q->p_opptr; - proc_reparent(q, t ? t : initproc); + proc_reparent(q, t ? t : + inst->i_initproc); q->p_opptr = NULL; } else - proc_reparent(q, initproc); + proc_reparent + (q, inst->i_initproc); q->p_flag &= ~(P_TRACED|P_WAITED|P_FSTRACE); psignal(q, SIGKILL); } else { - proc_reparent(q, initproc); + proc_reparent(q, inst->i_initproc); } } /* - * Move proc from allproc to zombproc, it's now ready - * to be collected by parent. Remaining lwp resources - * will be freed in lwp_exit2() once we've switch to idle - * context. - * Changing the state to SZOMB stops it being found by pfind(). + * Move proc from allproc to zombproc, it's now ready to be + * collected by parent. Remaining lwp resources will be freed in + * lwp_exit2() once we've switch to idle context. Changing the + * state to SZOMB stops it being found by pfind(). */ LIST_REMOVE(p, p_list); - LIST_INSERT_HEAD(&zombproc, p, p_list); + LIST_INSERT_HEAD(&p->p_inst->i_zombproc, p, p_list); p->p_stat = SZOMB; LIST_REMOVE(l, l_list); @@ -454,30 +518,35 @@ p->p_nrlwps--; p->p_nlwps--; - /* Put in front of parent's sibling list for parent to collect it */ - q = p->p_pptr; - q->p_nstopchild++; - if (LIST_FIRST(&q->p_children) != p) { - /* Put child where it can be found quickly */ - LIST_REMOVE(p, p_sibling); - LIST_INSERT_HEAD(&q->p_children, p, p_sibling); - } - - /* - * Notify parent that we're gone. If parent has the P_NOCLDWAIT - * flag set, notify init instead (and hope it will handle - * this situation). + /* + * Put in front of parent's sibling list for parent to collect + * it. This only occurs if we're not the instance root. */ - if (q->p_flag & P_NOCLDWAIT) { - proc_reparent(p, initproc); + q = p->p_pptr; + if (q) { + q->p_nstopchild++; + if (LIST_FIRST(&q->p_children) != p) { + /* Put child where it can be found quickly */ + LIST_REMOVE(p, p_sibling); + LIST_INSERT_HEAD(&q->p_children, p, p_sibling); + } /* - * If this was the last child of our parent, notify - * parent, so in case he was wait(2)ing, he will - * continue. + * Notify parent that we're gone. If parent has the + * P_NOCLDWAIT flag set, notify init instead (and hope + * it will handle this situation). */ - if (LIST_FIRST(&q->p_children) == NULL) - wakeup(q); + if (q->p_flag & P_NOCLDWAIT) { + proc_reparent(p, inst->i_initproc); + + /* + * If this was the last child of our parent, + * notify parent, so in case he was wait(2)ing, + * he will continue. + */ + if (LIST_FIRST(&q->p_children) == NULL) + wakeup(q); + } } /* @@ -502,25 +571,36 @@ p->p_sigacts = NULL; /* Reload parent pointer, since p may have been reparented above */ - q = p->p_pptr; + q = p->p_pptr; if ((p->p_flag & P_FSTRACE) == 0 && p->p_exitsig != 0) { - exit_psignal(p, q, &ksi); + if (q) + exit_psignal(p, q, &ksi); do_psignal = 1; } /* * Once we release the proclist lock, we shouldn't touch the - * process structure anymore, since it's now on the zombie - * list and available for collection by the parent. + * process structure anymore, since it's now on the zombie list + * and available for collection by the parent. */ - proclist_unlock_write(s); - - if (do_psignal) - kpsignal(q, &ksi, NULL); + proclist_unlock_write(p->p_inst, s); + + if (q) { + if (do_psignal) + kpsignal(q, &ksi, NULL); + /* Wake up the parent so it can get exit status. */ + wakeup(q); + } - /* Wake up the parent so it can get exit status. */ - wakeup(q); + if (p->p_inst->i_state == INST_EXITING) { + /* + * FIXME: we should only do this if we're the last ones + * left. + */ + instdaemon_sem = 1; + wakeup((void *)&instdaemon_sem); + } /* Release substructures */ sigactsfree(ps); @@ -559,6 +639,7 @@ lwpid_t waited; p = l->l_proc; + KASSERT(NULL != p); /* XXX SMP * This would be the right place to IPI any LWPs running on @@ -573,16 +654,12 @@ * Make SA-cached LWPs normal process runnable * LWPs so that they'll also self-destruct. */ - DPRINTF(("exit_lwps: Making cached LWPs of %d on VP %d runnable: ", - p->p_pid, vp->savp_id)); SCHED_LOCK(s); while ((l2 = sa_getcachelwp(vp)) != 0) { l2->l_priority = l2->l_usrpri; setrunnable(l2); - DPRINTF(("%d ", l2->l_lid)); } SCHED_UNLOCK(s); - DPRINTF(("\n")); /* * Clear wokenq, the LWPs on the queue will @@ -605,16 +682,12 @@ if ((l2->l_stat == LSSLEEP && (l2->l_flag & L_SINTR)) || l2->l_stat == LSSUSPENDED || l2->l_stat == LSSTOP) { setrunnable(l2); - DPRINTF(("exit_lwps: Made %d.%d runnable\n", - p->p_pid, l2->l_lid)); } SCHED_UNLOCK(s); } while (p->p_nlwps > 1) { - DPRINTF(("exit_lwps: waiting for %d LWPs (%d runnable, %d zombies)\n", - p->p_nlwps, p->p_nrlwps, p->p_nzlwps)); error = lwp_wait1(l, 0, &waited, LWPWAIT_EXITCONTROL); if (error == EDEADLK) { /* @@ -627,7 +700,6 @@ if (error) panic("exit_lwps: lwp_wait1 failed with error %d\n", error); - DPRINTF(("exit_lwps: Got LWP %d from lwp_wait1()\n", waited)); } p->p_userret = NULL; @@ -711,17 +783,21 @@ find_stopped_child(struct proc *parent, pid_t pid, int options, struct proc **child_p) { - struct proc *child; - int error; + struct proc *child; + int error; + + KASSERT(NULL != parent); + KASSERT(NULL != parent->p_inst); for (;;) { - proclist_lock_read(); + proclist_lock_read(parent->p_inst); error = ECHILD; LIST_FOREACH(child, &parent->p_children, p_sibling) { if (pid >= 0) { if (child->p_pid != pid) { - child = p_find(pid, PFIND_ZOMBIE | - PFIND_LOCKED); + child = p_find(parent->p_inst, + pid, PFIND_ZOMBIE | + PFIND_LOCKED); if (child == NULL || child->p_pptr != parent) { child = NULL; @@ -766,7 +842,7 @@ break; } } - proclist_unlock_read(); + proclist_unlock_read(parent->p_inst); if (child != NULL || error != 0 || options & WNOHANG) { *child_p = child; return error; @@ -783,15 +859,21 @@ void proc_free(struct proc *p) { - struct proc *parent = p->p_pptr; - ksiginfo_t ksi; - int s; + struct proc *parent; + ksiginfo_t ksi; + int s; + struct inst *i; + KASSERT(p); + KASSERT(p->p_inst); KASSERT(p->p_nlwps == 0); KASSERT(p->p_nzlwps == 0); KASSERT(p->p_nrlwps == 0); KASSERT(LIST_EMPTY(&p->p_lwps)); + parent = p->p_pptr; + i = p->p_inst; + /* * If we got the child via ptrace(2) or procfs, and * the parent is different (meaning the process was @@ -800,10 +882,10 @@ * parent the exit signal. The rest of the cleanup * will be done when the old parent waits on the child. */ - if ((p->p_flag & P_TRACED) && p->p_opptr != parent){ + if (parent && (p->p_flag & P_TRACED) && p->p_opptr != parent) { parent = p->p_opptr; if (parent == NULL) - parent = initproc; + parent = i->i_initproc; proc_reparent(p, parent); p->p_opptr = NULL; p->p_flag &= ~(P_TRACED|P_WAITED|P_FSTRACE); @@ -815,10 +897,12 @@ return; } - scheduler_wait_hook(parent, p); + if (parent) + scheduler_wait_hook(parent, p); p->p_xstat = 0; - ruadd(&parent->p_stats->p_cru, p->p_ru); + if (parent) + ruadd(&parent->p_stats->p_cru, p->p_ru); /* * At this point we are going to start freeing the final resources. @@ -837,24 +921,28 @@ */ leavepgrp(p); - s = proclist_lock_write(); - LIST_REMOVE(p, p_list); /* off zombproc */ - p->p_pptr->p_nstopchild--; - LIST_REMOVE(p, p_sibling); - proclist_unlock_write(s); + if (p->p_pptr) { + s = proclist_lock_write(i); + LIST_REMOVE(p, p_list); /* off zombproc */ + p->p_pptr->p_nstopchild--; + LIST_REMOVE(p, p_sibling); + proclist_unlock_write(i, s); + } /* * Decrement the count of procs running with this uid. */ - (void)chgproccnt(p->p_cred->p_ruid, -1); + (void)chgproccnt(i, p->p_cred->p_ruid, -1); /* * Free up credentials. */ + if (--p->p_cred->p_refcnt == 0) { crfree(p->p_cred->pc_ucred); - pool_put(&pcred_pool, p->p_cred); + pcred_free(p->p_cred); } + KASSERT(i->i_refcnt >= 1); /* * Release reference to text vnode @@ -867,7 +955,7 @@ sa_release(p); /* Free proc structure and let pid be reallocated */ - proc_free_mem(p); + proc_free_mem(i, p); } /* @@ -887,7 +975,7 @@ child->p_pptr->p_nstopchild--; parent->p_nstopchild++; } - if (parent == initproc) + if (parent == parent->p_inst->i_initproc) child->p_exitsig = SIGCHLD; LIST_REMOVE(child, p_sibling); diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_fork.c mult-netbsd-3.1/sys/kern/kern_fork.c --- NetBSD-3.1/sys/kern/kern_fork.c 2005-05-23 20:09:56.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_fork.c 2007-12-16 14:56:45.000000000 +0000 @@ -79,7 +79,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.121.2.2 2005/05/23 19:09:56 riz Exp $"); #include "opt_ktrace.h" -#include "opt_systrace.h" #include "opt_multiprocessor.h" #include @@ -99,21 +98,44 @@ #include #include #include -#include #include #include +#include + #include -int nprocs = 1; /* process 0 */ +extern const struct emul emul_netbsd; + +struct inst_fork +{ + int forkfsleep; /* Sleep ticks on fork-fail. */ +}; + + +int +inst_fork_alloc(inst_fork_t *p, int flags) +{ + struct inst_fork *i; + + KASSERT(p); + i = malloc(sizeof(struct inst_fork), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_fork)); + *p = i; + return(1); +} + +void +inst_fork_free(inst_fork_t p) +{ + KASSERT(p); + free(p, M_INST); +} -/* - * Number of ticks to sleep if fork() would fail due to process hitting - * limits. Exported in miliseconds to userland via sysctl. - */ -int forkfsleep = 0; /*ARGSUSED*/ int @@ -204,14 +226,212 @@ /* print the 'table full' message once per 10 seconds */ struct timeval fork_tfmrate = { 10, 0 }; + + +int +forkinst1(void (*func)(void *), void *arg, const char *path, + register_t *retval, struct proc **rnewprocp) +{ + struct proc *p1, *p2; + struct lwp *l2; + struct inst *i1, *i2; + uid_t uid; + int s; + vaddr_t uaddr; + boolean_t inmem; + + p1 = lwp0.l_proc; + uid = p1->p_cred->p_ruid; + i1 = lwp0.l_inst; + + KASSERT(i1); + + /* Reserve space for U-area (easy abortion). */ + inmem = uvm_uarea_alloc(&uaddr); + if (__predict_false(0 == uaddr)) + return (ENOMEM); + + /* + * We are now committed to the fork. From here on, we may + * block on resources, but resource allocation may NOT fail. + */ + + /* Allocate new instance and proc. */ + i2 = inst_alloc(INST_WAIT); + p2 = proc_alloc(i2); + i2->i_nprocs++; + (void)chgproccnt(i2, 0, 1); + + KASSERT(path); + + strlcpy(i2->i_root, path, MAXPATHLEN); + + /* + * Make a proc table entry for the new process. Start by + * zeroing the section of proc that is zero-initialized, then + * copy the section that is copied directly from the parent. + */ + memset(&p2->p_startzero, 0, (unsigned) + ((caddr_t)&p2->p_endzero - + (caddr_t)&p2->p_startzero)); + memcpy(&p2->p_startcopy, &p1->p_startcopy, (unsigned) + ((caddr_t)&p2->p_endcopy - + (caddr_t)&p2->p_startcopy)); + + simple_lock_init(&p2->p_sigctx.ps_silock); + CIRCLEQ_INIT(&p2->p_sigctx.ps_siginfo); + simple_lock_init(&p2->p_lock); + LIST_INIT(&p2->p_lwps); + + /* + * Duplicate sub-structures as needed. Increase reference + * counts on shared objects. The p_stats and p_sigacts + * substructs are set in uvm_fork(). Inherit SUGID, STOPFORK + * and STOPEXEC flags. + */ + p2->p_flag = p1->p_flag & (P_SUGID | P_STOPFORK | P_STOPEXEC); + p2->p_emul = p1->p_emul; + p2->p_execsw = p1->p_execsw; + p2->p_pptr = NULL; + + p2->p_cred = pcred_alloc(); + p2->p_cred->p_refcnt = 1; + p2->p_cred->pc_ucred = crget(i2); + + LIST_INIT(&p2->p_raslist); +#if defined(__HAVE_RAS) + ras_fork(p1, p2); +#endif + + /* bump references to the text vnode (for procfs) */ + p2->p_textvp = p1->p_textvp; + if (p2->p_textvp) + VREF(p2->p_textvp); + + p2->p_fd = fdinit(); + p2->p_cwdi = cwdinit(p1); + p2->p_limit = limcopy(p1->p_limit); + + if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) + p2->p_flag |= P_CONTROLT; + LIST_INIT(&p2->p_children); + + s = proclist_lock_write(p2->p_inst); + LIST_INSERT_AFTER(p1, p2, p_pglist); + proclist_unlock_write(p2->p_inst, s); + + scheduler_fork_hook(p1, p2); + + /* + * Create signal actions for the child process. + */ + sigactsinit(p2, p1, FALSE); + + /* + * p_stats. Copy parts of p_stats, and zero out the rest. + */ + p2->p_stats = pstatscopy(p1->p_stats); + + /* + * If emulation has process fork hook, call it now. + */ + if (p2->p_emul->e_proc_fork) + (*p2->p_emul->e_proc_fork)(p2, p1, 0); + + /* + * ...and finally, any other random fork hooks that subsystems + * might have registered. + */ + doforkhooks(p2, p1); + + /* + * This begins the section where we must prevent the parent + * from being swapped. + */ + PHOLD(&lwp0); + + uvm_proc_fork(p1, p2, FALSE); + + /* + * Finish creating the child process. It will return through a + * different path later. + */ + newlwp(&lwp0, p2, uaddr, inmem, 0, NULL, 0, + (func != NULL) ? func : child_return, + arg, &l2); + + /* Now safe for scheduler to see child process */ + s = proclist_lock_write(p2->p_inst); + /* Signal for parent on exit. */ + LIST_INSERT_HEAD(&p2->p_inst->i_allproc, p2, p_list); + proclist_unlock_write(p2->p_inst, s); + +#ifdef __HAVE_SYSCALL_INTERN + (*p2->p_emul->e_syscall_intern)(p2); +#endif + + /* + * Make child runnable, set start time, and add to run queue + * except if the parent requested the child to start in SSTOP state. + */ + SCHED_LOCK(s); + p2->p_stats->p_start = time; + p2->p_acflag = AFORK; + p2->p_nrlwps = 1; + p2->p_stat = SACTIVE; + l2->l_stat = LSRUN; + setrunqueue(l2); + SCHED_UNLOCK(s); + + /* + * Now can be swapped. + */ + PRELE(&lwp0); + + /* + * Notify any interested parties about the new process. + */ + KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid); + + /* + * Update stats now that we know the fork was successful. + */ + uvmexp.forks++; + + /* + * Pass a pointer to the new process to the caller. + */ + if (rnewprocp != NULL) + *rnewprocp = p2; + +#ifdef KTRACE + if (KTRPOINT(p2, KTR_EMUL)) + p2->p_traceflag |= KTRFAC_TRC_EMUL; +#endif + + /* + * Return child pid to parent process, marking us as parent via + * retval[1]. + */ + if (retval != NULL) { + retval[0] = p2->p_pid; + retval[1] = 0; + } + + return (0); +} + + + int fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, void (*func)(void *), void *arg, register_t *retval, struct proc **rnewprocp) { struct proc *p1, *p2, *parent; - uid_t uid; struct lwp *l2; + struct inst *i1; + uid_t uid; int count, s; vaddr_t uaddr; boolean_t inmem; @@ -225,29 +445,37 @@ */ p1 = l1->l_proc; uid = p1->p_cred->p_ruid; - if (__predict_false((nprocs >= maxproc - 5 && uid != 0) || - nprocs >= maxproc)) { + i1 = l1->l_inst; + + KASSERT(NULL != i1); + + /* FIXME - instances - lock instance for i_nprocs? */ + + if (__predict_false((i1->i_nprocs >= maxproc - 5 && uid != 0) || + i1->i_nprocs >= maxproc)) { static struct timeval lasttfm; if (ratecheck(&lasttfm, &fork_tfmrate)) tablefull("proc", "increase kern.maxproc or NPROC"); - if (forkfsleep) - (void)tsleep(&nprocs, PUSER, "forkmx", forkfsleep); + if (i1->i_fork->forkfsleep) + (void)tsleep(&i1->i_nprocs, PUSER, "forkmx", + i1->i_fork->forkfsleep); return (EAGAIN); } - nprocs++; + i1->i_nprocs++; /* * Increment the count of procs running with this uid. Don't allow * a nonprivileged user to exceed their current limit. */ - count = chgproccnt(uid, 1); + count = chgproccnt(i1, uid, 1); if (__predict_false(uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur)) { - (void)chgproccnt(uid, -1); - nprocs--; - if (forkfsleep) - (void)tsleep(&nprocs, PUSER, "forkulim", forkfsleep); + (void)chgproccnt(i1, uid, -1); + i1->i_nprocs--; + if (i1->i_fork->forkfsleep) + (void)tsleep(&i1->i_nprocs, PUSER, "forkulim", + i1->i_fork->forkfsleep); return (EAGAIN); } @@ -260,8 +488,8 @@ inmem = uvm_uarea_alloc(&uaddr); if (__predict_false(uaddr == 0)) { - (void)chgproccnt(uid, -1); - nprocs--; + (void)chgproccnt(i1, uid, -1); + i1->i_nprocs--; return (ENOMEM); } @@ -271,7 +499,7 @@ */ /* Allocate new proc. */ - p2 = proc_alloc(); + p2 = proc_alloc(l1->l_inst); /* * Make a proc table entry for the new process. @@ -300,10 +528,20 @@ if (p1->p_flag & P_PROFIL) startprofclock(p2); - p2->p_cred = pool_get(&pcred_pool, PR_WAITOK); + p2->p_cred = pcred_alloc(); + + /* + * NB: this will copy over the pc_ucred pointer, and thus the + * instance pointer, too. + */ memcpy(p2->p_cred, p1->p_cred, sizeof(*p2->p_cred)); p2->p_cred->p_refcnt = 1; + + /* + * Bump reference counts on both the user and the instance. + */ crhold(p1->p_ucred); + inst_hold(p1->p_inst); LIST_INIT(&p2->p_raslist); #if defined(__HAVE_RAS) @@ -318,7 +556,7 @@ if (flags & FORK_SHAREFILES) fdshare(p1, p2); else if (flags & FORK_CLEANFILES) - p2->p_fd = fdinit(p1); + p2->p_fd = fdinit(); else p2->p_fd = fdcopy(p1); @@ -346,14 +584,15 @@ p2->p_flag |= P_CONTROLT; if (flags & FORK_PPWAIT) p2->p_flag |= P_PPWAIT; - parent = (flags & FORK_NOWAIT) ? initproc : p1; + parent = (flags & FORK_NOWAIT) ? + i1->i_initproc : p1; p2->p_pptr = parent; LIST_INIT(&p2->p_children); - s = proclist_lock_write(); + s = proclist_lock_write(p2->p_inst); LIST_INSERT_AFTER(p1, p2, p_pglist); LIST_INSERT_HEAD(&parent->p_children, p2, p_sibling); - proclist_unlock_write(s); + proclist_unlock_write(p2->p_inst, s); #ifdef KTRACE /* @@ -409,16 +648,10 @@ arg, &l2); /* Now safe for scheduler to see child process */ - s = proclist_lock_write(); + s = proclist_lock_write(p2->p_inst); p2->p_exitsig = exitsig; /* signal for parent on exit */ - LIST_INSERT_HEAD(&allproc, p2, p_list); - proclist_unlock_write(s); - -#ifdef SYSTRACE - /* Tell systrace what's happening. */ - if (ISSET(p1->p_flag, P_SYSTRACE)) - systrace_sys_fork(p1, p2); -#endif + LIST_INSERT_HEAD(&p2->p_inst->i_allproc, p2, p_list); + proclist_unlock_write(p2->p_inst, s); #ifdef __HAVE_SYSCALL_INTERN (*p2->p_emul->e_syscall_intern)(p2); @@ -511,3 +744,60 @@ KERNEL_PROC_LOCK(l); } #endif + +#include + +static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO); + +/* + * sysctl helper routine for kern.forkfsleep node. ensures that the + * given value is not too large or two small, and is at least one timer + * tick if not zero. + */ +static int +sysctl_kern_forkfsleep(SYSCTLFN_ARGS) +{ + /* userland sees value in ms, internally is in ticks */ + int error, timo, lsleep; + struct sysctlnode node; + + lsleep = l->l_inst->i_fork->forkfsleep * 1000 / hz; + node = *rnode; + node.sysctl_data = &lsleep; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return (error); + + /* refuse negative values, and overly 'long time' */ + if (lsleep < 0 || lsleep > MAXSLP * 1000) + return (EINVAL); + + timo = mstohz(lsleep); + + /* if the interval is >0 ms && <1 tick, use 1 tick */ + if (lsleep != 0 && timo == 0) + l->l_inst->i_fork->forkfsleep = 1; + else + l->l_inst->i_fork->forkfsleep = timo; + + return (0); +} + + +SYSCTL_SETUP(sysctl_kern_forkfsleep_setup, + "sysctl kern.forkfsleep setup") +{ + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "kern", NULL, + NULL, 0, NULL, 0, + CTL_KERN, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "forkfsleep", + SYSCTL_DESCR("Milliseconds to sleep on fork " + "failure due to process limits"), + sysctl_kern_forkfsleep, 0, NULL, 0, + CTL_KERN, KERN_FORKFSLEEP, CTL_EOL); +} + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_inst.c mult-netbsd-3.1/sys/kern/kern_inst.c --- NetBSD-3.1/sys/kern/kern_inst.c 1970-01-01 01:00:00.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_inst.c 2007-12-19 13:35:20.000000000 +0000 @@ -0,0 +1,817 @@ +/* + * Copyright (c) 2007 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +MALLOC_DEFINE(M_INST, "inst", "Instance sub-structures"); + +static int inst_debug = 0; +static struct inst *insttbl[INST_MAX]; +static struct lock instlist_rw_lock; +static u_int instlist_cnt; +static POOL_INIT(inst_pool, sizeof(struct inst), + 0, 0, 0, "inst_pool", NULL); + +void instinit(void *); +static int instctl_debug(int, struct inst *); +static int instctl_create(const struct instctl_create *, + struct inst *); +static int instctl_kill(const struct instctl_kill *, + struct inst *); +static int instchroot(struct proc *); +static int instlist_lock_rw(void); +static void instlist_unlock_rw(int); +static void inst_log(int lvl, const char *, + const struct inst *, + const char *, ...) + __attribute__((__format__ + (__printf__, 4, 5))); +static void inst_free(struct inst *); + +#define inst_refcnt_inc(inst) \ + simple_lock(&(inst)->i_lock); \ + (inst)->i_refcnt++; \ + inst_log(IC_REFCNT, __func__, (inst), "refcnt: %d", \ + (inst)->i_refcnt); \ + simple_unlock(&(inst)->i_lock); + +#define inst_refcnt_dec(val, inst) \ + simple_lock(&(inst)->i_lock); \ + (val) = --(inst)->i_refcnt; \ + inst_log(IC_REFCNT, __func__, (inst), "refcnt: %d", \ + (inst)->i_refcnt); \ + simple_unlock(&(inst)->i_lock); + +static void +inst_log(int lvl, const char *func, + const struct inst *inst, const char *fmt, ...) +{ + va_list ap; + size_t sz; + char dbuf[256], *p; + int uuid; + + if ( ! (inst_debug & lvl)) + return; + + /* FIXME: this will overflow. */ + uuid = inst ? (int)inst->i_uuid : -1; + + KASSERT(func); + KASSERT(fmt); + + dbuf[255] = 0; + snprintf(dbuf, 255, "%s uuid %d: ", func, uuid); + + sz = strlen(dbuf); + p = dbuf + sz; + va_start(ap, fmt); + vsnprintf(p, 255 - sz, fmt, ap); + va_end(ap); + printf("%s\n", dbuf); +} + + +void +inst_init(void) +{ + spinlockinit(&instlist_rw_lock, "instlk", 0); + LIST_INIT(&allinst); + instlist_cnt = 0; + memset(insttbl, 0, sizeof(insttbl)); +} + + +void +inst_get_phostname(struct proc *proc, char *buf, size_t len) +{ + KASSERT(NULL != buf); + + if (NULL == proc) { + (void)strlcpy(buf, "", len); + return; + } + + KASSERT(NULL != proc->p_inst); + + simple_lock(&proc->p_inst->i_lock); + strlcpy(buf, proc->p_inst->i_host, len); + simple_unlock(&proc->p_inst->i_lock); +} + + +void +inst_get_hostname(struct lwp *l, char *buf, size_t len) +{ + if (NULL == l) { + KASSERT(NULL != buf); + (void)strlcpy(buf, "", len); + } else + inst_get_phostname(l->l_proc, buf, len); +} + + +int +inst_copyout_hostname(struct lwp *l, void *uaddr, size_t len) +{ + char tmp[MAXHOSTNAMELEN]; + + tmp[0] = 0; + + if (NULL != l) { + KASSERT(NULL != l->l_inst); + simple_lock(&l->l_inst->i_lock); + strlcpy(tmp, l->l_inst->i_host, MAXHOSTNAMELEN); + simple_unlock(&l->l_inst->i_lock); + } + + return(copyout(tmp, uaddr, len)); +} + + +int +inst_copyoutstr_hostname(struct lwp *l, + void *uaddr, size_t len, size_t *done) +{ + char tmp[MAXHOSTNAMELEN]; + + tmp[0] = 0; + + if (NULL != l) { + KASSERT(NULL != l->l_inst); + simple_lock(&l->l_inst->i_lock); + strlcpy(tmp, l->l_inst->i_host, MAXHOSTNAMELEN); + simple_unlock(&l->l_inst->i_lock); + } + + return(copyoutstr(tmp, uaddr, len, done)); +} + + +size_t +inst_get_phostnamelen(struct proc *proc) +{ + size_t sz; + + if (NULL == proc) + return(0); + + KASSERT(NULL != proc->p_inst); + + simple_lock(&proc->p_inst->i_lock); + sz = strlen(proc->p_inst->i_host); + simple_unlock(&proc->p_inst->i_lock); + + return(sz); +} + + +size_t +inst_get_hostnamelen(struct lwp *l) +{ + if (NULL == l) + return(0); + + return(inst_get_phostnamelen(l->l_proc)); +} + + +void +inst_get_pdomainname(struct proc *proc, char *buf, size_t len) +{ + KASSERT(NULL != buf); + + if (NULL == proc) { + (void)strlcpy(buf, "", len); + return; + } + + KASSERT(NULL != proc->p_inst); + + simple_lock(&proc->p_inst->i_lock); + strlcpy(buf, proc->p_inst->i_domain, len); + simple_unlock(&proc->p_inst->i_lock); +} + + +void +inst_get_domainname(struct lwp *l, char *buf, size_t len) +{ + if (NULL == l) { + KASSERT(NULL != buf); + (void)strlcpy(buf, "", len); + } else + inst_get_pdomainname(l->l_proc, buf, len); +} + + +size_t +inst_get_pdomainnamelen(struct proc *proc) +{ + size_t sz; + + if (NULL == proc) + return(0); + + KASSERT(NULL != proc->p_inst); + + simple_lock(&proc->p_inst->i_lock); + sz = strlen(proc->p_inst->i_domain); + simple_unlock(&proc->p_inst->i_lock); + + return(sz); +} + + +size_t +inst_get_domainnamelen(struct lwp *l) +{ + if (NULL == l) + return(0); + + return(inst_get_pdomainnamelen(l->l_proc)); +} + + +int +inst_set_hostname(struct lwp *l, const char *buf) +{ + if (NULL == l) + return(EINVAL); + + KASSERT(l->l_inst); + KASSERT(buf); + + simple_lock(&l->l_inst->i_lock); + strlcpy(l->l_inst->i_host, buf, MAXHOSTNAMELEN); + simple_unlock(&l->l_inst->i_lock); + + return(0); +} + + +int +inst_set_domainname(struct lwp *l, const char *buf) +{ + if (NULL == l) + return(EINVAL); + + KASSERT(NULL != l->l_inst); + KASSERT(NULL != buf); + + simple_lock(&l->l_inst->i_lock); + strlcpy(l->l_inst->i_domain, buf, MAXHOSTNAMELEN); + simple_unlock(&l->l_inst->i_lock); + + return(0); +} + + +struct inst * +inst_alloc(int flag) +{ + struct inst *i; + int s, pflag, mflag; + + pflag = flag & INST_WAIT ? PR_WAITOK : PR_NOWAIT; + mflag = flag & INST_WAIT ? M_WAITOK : M_NOWAIT; + + i = pool_get(&inst_pool, pflag); + (void)memset(i, 0, sizeof(struct inst)); + + i->i_refcnt = 1; + i->i_state = INST_INIT; + + simple_lock_init(&i->i_lock); + + /* + * Initialise live-in process stuff. + */ + + i->i_proclists[0].pd_list = &i->i_allproc; + i->i_proclists[1].pd_list = &i->i_zombproc; + i->i_proclists[2].pd_list = NULL; + + spinlockinit(&i->i_proclist_lock, "proclk", 0); + + /* + * Initialise live-in file stuff. + */ + + simple_lock_init(&i->i_filelist_lock); + + /* + * Initialise sub-structures. + */ + + /* TODO: release extant resources. */ + if ( ! inst_proc_alloc(&i->i_proc, mflag)) + return(NULL); + if ( ! inst_acct_alloc(&i->i_acct, mflag)) + return(NULL); + if ( ! inst_res_alloc(&i->i_res, mflag)) + return(NULL); + if ( ! inst_pipe_alloc(&i->i_pipe, mflag)) + return(NULL); + if ( ! inst_kevt_alloc(&i->i_kevt, mflag)) + return(NULL); + if ( ! inst_fork_alloc(&i->i_fork, mflag)) + return(NULL); + if ( ! inst_ktrc_alloc(&i->i_ktrc, mflag)) + return(NULL); + + /* + * FIXME. Use an real method for instance identifiers so that + * we can later do lookups based on instances. Use the proc + * method or something. This dies after INSTLIST_MAX tries. + */ + + s = instlist_lock_rw(); + KASSERT(instlist_cnt < INST_MAX); + KASSERT(NULL == insttbl[instlist_cnt]); + i->i_uuid = instlist_cnt++; + insttbl[i->i_uuid] = i; + LIST_INSERT_HEAD(&allinst, i, i_list); + instlist_unlock_rw(s); + + inst_log(IC_ALLOC, __func__, i, "alloc: %u", i->i_uuid); + + return(i); +} + + +static void +inst_free(struct inst *i) +{ + int sp; + + inst_log(IC_ALLOC, __func__, i, "free: %u", i->i_uuid); + + sp = instlist_lock_rw(); + KASSERT(insttbl[i->i_uuid]); + insttbl[i->i_uuid] = NULL; + LIST_REMOVE(i, i_list); + instlist_unlock_rw(sp); + + if (i->i_ktrc) + inst_ktrc_free(i->i_ktrc); + if (i->i_fork) + inst_fork_free(i->i_fork); + if (i->i_kevt) + inst_kevt_free(i->i_kevt); + if (i->i_acct) + inst_acct_free(i->i_acct); + if (i->i_res) + inst_res_free(i->i_res); + if (i->i_proc) + inst_proc_free(i->i_proc); + if (i->i_proc) + inst_pipe_free(i->i_pipe); + + pool_put(&inst_pool, i); +} + + +void +inst_hold(struct inst *inst) +{ + KASSERT(inst); + KASSERT(inst->i_refcnt > 0); + inst_refcnt_inc(inst); +} + + +void +inst_release(struct inst *inst) +{ + uint refcnt; + + KASSERT(NULL != inst); + KASSERT(inst->i_refcnt > 0); + inst_refcnt_dec(refcnt, inst); + if (0 != refcnt) + return; + inst_free(inst); +} + + +static int +instlist_lock_rw(void) +{ + int s, error; + s = splclock(); + error = spinlockmgr(&instlist_slock, LK_EXCLUSIVE, NULL); + if (__predict_false(0 != error)) + panic("failed to acquire instance lock"); + return(s); +} + + +static void +instlist_unlock_rw(int s) +{ + (void)spinlockmgr(&instlist_slock, LK_RELEASE, NULL); + splx(s); +} + + +void +instlist_lock_read(void) +{ + int error; + error = spinlockmgr(&instlist_slock, LK_SHARED, NULL); + if (__predict_false(0 != error)) + panic("failed to acquire instance lock"); +} + + +void +instlist_unlock_read(void) +{ + (void)spinlockmgr(&instlist_slock, LK_RELEASE, NULL); +} + + +static int +instctl_debug(int ctl, struct inst *i) +{ + KASSERT(i); + inst_log(IC_SYSCALL, __func__, i, + "debug level: %x -> %x", inst_debug, ctl); + + simple_lock(&i->i_lock); + inst_debug = ctl; + simple_unlock(&i->i_lock); + return(0); +} + + +static int +instctl_create(const struct instctl_create *ctl, struct inst *i) +{ + char path[MAXPATHLEN]; + int error; + + KASSERT(i); + KASSERT(ctl); + if (NULL == ctl->root) + return(EINVAL); + + error = copyinstr(ctl->root, path, MAXPATHLEN, NULL); + if (error) + return(error); + + inst_log(IC_SYSCALL, __func__, i, "fork: %s", path); + return(forkinst1(instinit, NULL, path, NULL, NULL)); +} + + +static int +instctl_kill(const struct instctl_kill *ctl, struct inst *i) +{ + struct inst *ci; + + ci = inst_lookup(ctl->uuid); + if (NULL == ci) + return(ESRCH); + psignal1(ci->i_initproc, IC_KILLSLOW == ctl->sig ? + SIGTERM : SIGKILL, 1); + inst_release(ci); + return(0); +} + + +int +/* ARGSUSED */ +sys_instctl(struct lwp *l, void *v, register_t *retval) +{ + struct sys_instctl_args /* { + syscallarg(const struct instctl *) ctl; + } */ *uap = v; + const struct instctl *ctl; + struct inst *i; + + KASSERT(l); + KASSERT(l->l_inst); + ctl = SCARG(uap, ctl); + + i = l->l_inst; + switch (ctl->ic_op) { + case (IC_CREATE): + return(instctl_create(&ctl->ic_data.ic_create, i)); + case (IC_DEBUG): + return(instctl_debug(ctl->ic_data.ic_debug, i)); + case (IC_KILL): + return(instctl_kill(&ctl->ic_data.ic_kill, i)); + default: + break; + } + return (EINVAL); +} + + +struct inst * +inst_lookup(u_int uuid) +{ + struct inst *i; + + if (uuid >= INST_MAX) + return(NULL); + + instlist_lock_read(); + i = insttbl[uuid]; + if (i) + inst_hold(i); + instlist_unlock_read(); + + return(i); +} + + +static const char *initpaths[] = { + "/sbin/instinit", + "/sbin/instinit.bak", + NULL, +}; + + +void +instinit(void *arg) +{ + struct lwp *l = arg; + struct proc *p = l->l_proc; + vaddr_t addr; + struct sys_execve_args /* { + syscallarg(const char *) path; + syscallarg(char * const *) argp; + syscallarg(char * const *) envp; + } */ args; + int options, i, error; + register_t retval[2]; + char flags[4], *flagsp; + const char *path, *slash; + char *ucp, **uap, *arg0, *arg1 = NULL; + int ipx; + + /* + * Now in process 1. + */ + strncpy(p->p_comm, "init", MAXCOMLEN); + p->p_inst->i_initproc = p; + p->p_inst->i_state = INST_RUNNING; + + if (0 != (error = instchroot(p))) { + inst_log(IC_SYSCALL, __func__, p->p_inst, + "chroot: %s", p->p_inst->i_root); + goto out; + } + + /* + * Need just enough stack to hold the faked-up "execve()" arguments. + */ + addr = (vaddr_t)STACK_ALLOC(USRSTACK, PAGE_SIZE); + if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY, + UVM_ADV_NORMAL, + UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) != 0) + panic("init: couldn't allocate argument space"); + p->p_vmspace->vm_maxsaddr = (caddr_t)STACK_MAX(addr, PAGE_SIZE); + + ipx = 0; + for (;; /* Infinite loop. */) { + if ((path = initpaths[ipx++]) == NULL) + break; + + ucp = (char *)USRSTACK; + + /* + * Construct the boot flag argument. + */ + flagsp = flags; + *flagsp++ = '-'; + options = 0; + + /* + * Move out the file name (also arg 0). + */ + i = strlen(path) + 1; + arg0 = STACK_ALLOC(ucp, i); + ucp = STACK_MAX(arg0, i); + (void)copyout((const caddr_t)path, arg0, i); + + /* + * Move out the arg pointers. + */ + ucp = (caddr_t)STACK_ALIGN(ucp, ALIGNBYTES); + uap = (char **)STACK_ALLOC(ucp, sizeof(char *) * 3); + SCARG(&args, path) = arg0; + SCARG(&args, argp) = uap; + SCARG(&args, envp) = NULL; + slash = strrchr(path, '/'); + if (slash) + (void)suword((caddr_t)uap++, + (long)arg0 + (slash + 1 - path)); + else + (void)suword((caddr_t)uap++, (long)arg0); + if (options != 0) + (void)suword((caddr_t)uap++, (long)arg1); + (void)suword((caddr_t)uap++, 0); /* terminator */ + + /* + * Now try to exec the program. If can't for any reason + * other than it doesn't exist, complain. + */ + error = sys_execve(LIST_FIRST(&p->p_lwps), &args, retval); + if (error == 0 || error == EJUSTRETURN) { + KERNEL_PROC_UNLOCK(l); + return; + } + + inst_log(IC_SYSCALL, __func__, p->p_inst, + "exec: %s, %d", path, error); + } + +out: + inst_log(IC_SYSCALL, __func__, p->p_inst, + "instance death: cannot fork"); + + p->p_inst->i_state = INST_EXITING; + instdaemon_sem = 1; + wakeup((void *)&instdaemon_sem); + + exit1(LIST_FIRST(&p->p_lwps), 1); +} + + +/* + * This is yanked from sys_chroot. + */ +static int +instchroot(struct proc *p) +{ + int error; + struct nameidata nd; + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, + UIO_SYSSPACE, p->p_inst->i_root, p); + + if (0 != (error = namei(&nd))) + return (error); + + error = nd.ni_vp->v_type != VDIR ? ENOTDIR : + VOP_ACCESS(nd.ni_vp, VEXEC, p->p_ucred, p); + + if (error) { + vput(nd.ni_vp); + return(error); + } else + VOP_UNLOCK(nd.ni_vp, 0); + + if (p->p_cwdi->cwdi_rdir != NULL) + vrele(p->p_cwdi->cwdi_rdir); + p->p_cwdi->cwdi_rdir = nd.ni_vp; + + /* + * Prevent escaping from chroot by putting the root under the + * working directory. Silently chdir to / if we aren't already + * there. + */ + if (!vn_isunder(p->p_cwdi->cwdi_cdir, nd.ni_vp, p)) { + /* + * XXX would be more failsafe to change directory to a + * deadfs node here instead. + */ + vrele(p->p_cwdi->cwdi_cdir); + VREF(nd.ni_vp); + p->p_cwdi->cwdi_cdir = nd.ni_vp; + } + + return (0); +} + + +void +proclist_lock_read(struct inst *i) +{ + int error; + + KASSERT(i); + error = spinlockmgr + (&i->i_proclist_lock, LK_SHARED, NULL); +#ifdef DIAGNOSTIC + if (__predict_false(0 != error)) + panic("proclist_lock_read: failed to acquire lock"); +#endif +} + + +void +proclist_unlock_read(struct inst *i) +{ + KASSERT(NULL != i); + (void)spinlockmgr(&i->i_proclist_lock, LK_RELEASE, NULL); +} + + +int +proclist_lock_write(struct inst *i) +{ + int s, error; + + s = splclock(); + KASSERT(i); + error = spinlockmgr(&i->i_proclist_lock, LK_EXCLUSIVE, NULL); +#ifdef DIAGNOSTIC + if (__predict_false(0 != error)) + panic("proclist_lock: failed to acquire lock"); +#endif + return(s); +} + + +void +proclist_unlock_write(struct inst *i, int s) +{ + KASSERT(i); + (void)spinlockmgr(&i->i_proclist_lock, LK_RELEASE, NULL); + splx(s); +} + + +/* + * This kernel-thread handles exited instinit(8) processes. See + * instdaemon(9). This should never exit! + */ +void +instdaemon(void *v) +{ + struct inst *i; + + (void)v; /* Stop lint from complaining. */ + + for (;;) { + while (0 == instdaemon_sem) + (void)tsleep((void *)&instdaemon_sem, + PWAIT, "instdaemon", 0); + instdaemon_sem = 0; + + inst_log(IC_DAEMON, __func__, NULL, "instdaemon woken"); + +again: + i = NULL; + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) + if (INST_EXITING == i->i_state && + 1 == i->i_nprocs) + break; + instlist_unlock_read(); + if (NULL == i) + continue; + + inst_log(IC_DAEMON, __func__, i, + "instdaemon reaping: %d", i->i_uuid); + + i->i_state = INST_REAPED; + proc_free(i->i_initproc); + goto again; + } +} diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_ktrace.c mult-netbsd-3.1/sys/kern/kern_ktrace.c --- NetBSD-3.1/sys/kern/kern_ktrace.c 2006-10-24 17:33:44.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_ktrace.c 2007-11-27 12:47:32.000000000 +0000 @@ -56,6 +56,8 @@ #include #include +#include + #ifdef KTRACE /* @@ -136,21 +138,55 @@ #define KTD_WAKEDELAY 5000 /* XXX: tune */ #define KTD_INTRWAKDL 100 /* XXX: tune */ -/* - * Patchable variables. - */ -int ktd_maxentry = KTD_MAXENTRY; /* max # of entry in the queue */ -int ktd_timeout = KTD_TIMEOUT; /* timeout in seconds */ -int ktd_delayqcnt = KTD_DELAYQCNT; /* # of entry allowed to delay */ -int ktd_wakedelay = KTD_WAKEDELAY; /* delay of wakeup in *ms* */ -int ktd_intrwakdl = KTD_INTRWAKDL; /* ditto, but when interactive */ -static struct simplelock ktdq_slock = SIMPLELOCK_INITIALIZER; -static TAILQ_HEAD(, ktr_desc) ktdq = TAILQ_HEAD_INITIALIZER(ktdq); +struct inst_ktrc +{ + struct simplelock ktdq_slock; + TAILQ_HEAD(, ktr_desc) ktdq; + int ktd_maxentry; /* max # of entry in the queue */ + int ktd_timeout; /* timeout in seconds */ + int ktd_delayqcnt; /* # of entry allowed to delay */ + int ktd_wakedelay; /* delay of wakeup in *ms* */ + int ktd_intrwakdl; /* ditto, but when interactive */ +}; + MALLOC_DEFINE(M_KTRACE, "ktrace", "ktrace data buffer"); + POOL_INIT(kte_pool, sizeof(struct ktrace_entry), 0, 0, 0, - "ktepl", &pool_allocator_nointr); + "ktepl", &pool_allocator_nointr); + + +int +inst_ktrc_alloc(inst_ktrc_t *p, int flags) +{ + struct inst_ktrc *i; + + KASSERT(p); + i = malloc(sizeof(struct inst_ktrc), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_ktrc)); + + simple_lock_init(&i->ktdq_slock); + TAILQ_INIT(&i->ktdq); + i->ktd_maxentry = KTD_MAXENTRY; + i->ktd_timeout = KTD_TIMEOUT; + i->ktd_delayqcnt = KTD_DELAYQCNT; + i->ktd_wakedelay = KTD_WAKEDELAY; + i->ktd_intrwakdl = KTD_INTRWAKDL; + + *p = i; + return(1); +} + +void +inst_ktrc_free(inst_ktrc_t p) +{ + KASSERT(p); + free(p, M_INST); +} + static __inline void ktd_wakeup(struct ktr_desc *ktd) @@ -211,8 +247,9 @@ { struct ktr_desc *ktd; - simple_lock(&ktdq_slock); - for (ktd = TAILQ_FIRST(&ktdq); ktd != NULL; + simple_lock(&fp->f_cred->cr_inst->i_ktrc->ktdq_slock); + for (ktd = TAILQ_FIRST(&fp->f_cred->cr_inst->i_ktrc->ktdq); + ktd != NULL; ktd = TAILQ_NEXT(ktd, ktd_list)) { simple_lock(&ktd->ktd_slock); if (ktrsamefile(ktd->ktd_fp, fp)) { @@ -222,7 +259,7 @@ } simple_unlock(&ktd->ktd_slock); } - simple_unlock(&ktdq_slock); + simple_unlock(&fp->f_cred->cr_inst->i_ktrc->ktdq_slock); return (ktd); } @@ -260,7 +297,7 @@ if (ktd->ktd_flags & KTDF_DONE) goto relktd; - if (ktd->ktd_qcount > ktd_maxentry) { + if (ktd->ktd_qcount > p->p_inst->i_ktrc->ktd_maxentry) { ktd_logerrl(ktd, KTDE_ENOSPC); goto relktd; } @@ -271,7 +308,7 @@ if (flags & KTA_WAITOK && (/* flags & KTA_LARGE */0 || ktd->ktd_flags & KTDF_WAIT || - ktd->ktd_qcount > ktd_maxentry >> 1)) + ktd->ktd_qcount > p->p_inst->i_ktrc->ktd_maxentry >> 1)) /* * Sync with writer thread since we're requesting rather * big one or many requests are pending. @@ -285,7 +322,8 @@ splx(s); #endif if (ltsleep(&ktd->ktd_flags, PWAIT, "ktrsync", - ktd_timeout * hz, &ktd->ktd_slock) != 0) { + p->p_inst->i_ktrc->ktd_timeout * hz, + &ktd->ktd_slock) != 0) { ktd->ktd_flags |= KTDF_BLOCKING; /* * Maybe the writer thread is blocking @@ -738,8 +776,9 @@ if (ktd == NULL) goto done; - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + KASSERT(NULL != curp->p_inst); + proclist_lock_read(curp->p_inst); + PROCLIST_FOREACH(p, &curp->p_inst->i_allproc) { if (p->p_tracep == ktd) { if (ktrcanset(curp, p)) ktrderef(p); @@ -747,7 +786,7 @@ error = EPERM; } } - proclist_unlock_read(); + proclist_unlock_read(curp->p_inst); goto done; case KTROP_SET: @@ -761,9 +800,9 @@ ktd->ktd_flags = ktd->ktd_qcount = ktd->ktd_error = ktd->ktd_errcnt = 0; ktd->ktd_ref = 1; - ktd->ktd_delayqcnt = ktd_delayqcnt; - ktd->ktd_wakedelay = mstohz(ktd_wakedelay); - ktd->ktd_intrwakdl = mstohz(ktd_intrwakdl); + ktd->ktd_delayqcnt = curp->p_inst->i_ktrc->ktd_delayqcnt; + ktd->ktd_wakedelay = mstohz(curp->p_inst->i_ktrc->ktd_wakedelay); + ktd->ktd_intrwakdl = mstohz(curp->p_inst->i_ktrc->ktd_intrwakdl); /* * XXX: not correct. needs an way to detect * whether ktruss or ktrace. @@ -783,9 +822,9 @@ simple_unlock(&fp->f_slock); ktd->ktd_fp = fp; - simple_lock(&ktdq_slock); - TAILQ_INSERT_TAIL(&ktdq, ktd, ktd_list); - simple_unlock(&ktdq_slock); + simple_lock(&curp->p_inst->i_ktrc->ktdq_slock); + TAILQ_INSERT_TAIL(&curp->p_inst->i_ktrc->ktdq, ktd, ktd_list); + simple_unlock(&curp->p_inst->i_ktrc->ktdq_slock); } break; @@ -808,7 +847,7 @@ /* * by process group */ - pg = pg_find(-pid, PFIND_UNLOCK_FAIL); + pg = pg_find(curp->p_inst, -pid, PFIND_UNLOCK_FAIL); if (pg == NULL) { error = ESRCH; goto done; @@ -824,7 +863,7 @@ /* * by pid */ - p = p_find(pid, PFIND_UNLOCK_FAIL); + p = p_find(curp->p_inst, pid, PFIND_UNLOCK_FAIL); if (p == NULL) { error = ESRCH; goto done; @@ -834,7 +873,8 @@ else ret |= ktrops(curp, p, ops, facs, ktd); } - proclist_unlock_read(); /* taken by p{g}_find */ + /* taken by p{g}_find */ + proclist_unlock_read(curp->p_inst); if (!ret) error = EPERM; done: @@ -1023,7 +1063,7 @@ continue; } for (;;) { - if (p == top) + if (NULL == p || p == top) return (ret); if (LIST_NEXT(p, p_sibling) != NULL) { p = LIST_NEXT(p, p_sibling); @@ -1100,12 +1140,13 @@ log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + KASSERT(NULL != ktd->ktd_proc->p_inst); + proclist_lock_read(ktd->ktd_proc->p_inst); + PROCLIST_FOREACH(p, &ktd->ktd_proc->p_inst->i_allproc) { if (p->p_tracep == ktd) ktrderef(p); } - proclist_unlock_read(); + proclist_unlock_read(ktd->ktd_proc->p_inst); } while ((kte = top) != NULL) { @@ -1152,9 +1193,9 @@ } simple_unlock(&ktd->ktd_slock); - simple_lock(&ktdq_slock); - TAILQ_REMOVE(&ktdq, ktd, ktd_list); - simple_unlock(&ktdq_slock); + simple_lock(&fp->f_cred->cr_inst->i_ktrc->ktdq_slock); + TAILQ_REMOVE(&fp->f_cred->cr_inst->i_ktrc->ktdq, ktd, ktd_list); + simple_unlock(&fp->f_cred->cr_inst->i_ktrc->ktdq_slock); simple_lock(&fp->f_slock); FILE_USE(fp); diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_lwp.c mult-netbsd-3.1/sys/kern/kern_lwp.c --- NetBSD-3.1/sys/kern/kern_lwp.c 2005-11-13 13:56:02.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_lwp.c 2007-11-23 10:17:19.000000000 +0000 @@ -54,18 +54,18 @@ #include #include +#include + #include -struct lwplist alllwp; -#define LWP_DEBUG +POOL_INIT(lwp_uc_pool, sizeof(ucontext_t), + 0, 0, 0, "lwpucpl", &pool_allocator_nointr); + +static POOL_INIT(lwp_pool, sizeof(struct lwp), + 0, 0, 0, "lwppl", &pool_allocator_nointr); + -#ifdef LWP_DEBUG -int lwp_debug = 0; -#define DPRINTF(x) if (lwp_debug) printf x -#else -#define DPRINTF(x) -#endif /* ARGSUSED */ int sys__lwp_create(struct lwp *l, void *v, register_t *retval) @@ -85,6 +85,8 @@ if (p->p_flag & P_SA) return EINVAL; + KASSERT(NULL != l->l_inst); + newuc = pool_get(&lwp_uc_pool, PR_WAITOK); error = copyin(SCARG(uap, ucp), newuc, sizeof(*newuc)); @@ -284,11 +286,6 @@ void lwp_continue(struct lwp *l) { - - DPRINTF(("lwp_continue of %d.%d (%s), state %d, wchan %p\n", - l->l_proc->p_pid, l->l_lid, l->l_proc->p_comm, l->l_stat, - l->l_wchan)); - if (l->l_stat != LSSUSPENDED) return; @@ -383,8 +380,7 @@ static const char waitstr1[] = "lwpwait"; static const char waitstr2[] = "lwpwait2"; - DPRINTF(("lwp_wait1: %d.%d waiting for %d.\n", - p->p_pid, l->l_lid, lid)); + KASSERT(NULL != p->p_inst); if (lid == l->l_lid) return (EDEADLK); /* Waiting for ourselves makes no sense. */ @@ -466,6 +462,9 @@ struct lwp *l2; int s; + KASSERT(NULL != l1); + KASSERT(NULL != l1->l_inst); + l2 = pool_get(&lwp_pool, PR_WAITOK); l2->l_stat = LSIDL; @@ -515,9 +514,10 @@ simple_unlock(&p2->p_lock); /* XXX should be locked differently... */ - s = proclist_lock_write(); - LIST_INSERT_HEAD(&alllwp, l2, l_list); - proclist_unlock_write(s); + KASSERT(NULL != l1->l_inst); + s = proclist_lock_write(l1->l_inst); + LIST_INSERT_HEAD(&l1->l_inst->i_alllwp, l2, l_list); + proclist_unlock_write(l1->l_inst, s); if (p2->p_emul->e_lwp_fork) (*p2->p_emul->e_lwp_fork)(l1, l2); @@ -527,19 +527,21 @@ /* - * Quit the process. This will call cpu_exit, which will call cpu_switch, - * so this can only be used meaningfully if you're willing to switch away. + * Quit the process. This will call cpu_exit, which will call cpu_switch, so + * this can only be used meaningfully if you're willing to switch away. * Calling with l!=curlwp would be weird. */ void lwp_exit(struct lwp *l) { - struct proc *p = l->l_proc; - int s; + struct proc *p; + struct inst *i; + int s; - DPRINTF(("lwp_exit: %d.%d exiting.\n", p->p_pid, l->l_lid)); - DPRINTF((" nlwps: %d nrlwps %d nzlwps: %d\n", - p->p_nlwps, p->p_nrlwps, p->p_nzlwps)); + p = l->l_proc; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + i = p->p_inst; if (p->p_emul->e_lwp_exit) (*p->p_emul->e_lwp_exit)(l); @@ -551,15 +553,13 @@ * exit, and because that's what Solaris does. */ if (((p->p_nlwps - p->p_nzlwps) == 1) && ((p->p_flag & P_WEXIT) == 0)) { - DPRINTF(("lwp_exit: %d.%d calling exit1()\n", - p->p_pid, l->l_lid)); exit1(l, 0); /* NOTREACHED */ } - s = proclist_lock_write(); + s = proclist_lock_write(i); LIST_REMOVE(l, l_list); - proclist_unlock_write(s); + proclist_unlock_write(i, s); /* Free MD LWP resources */ #ifndef __NO_CPU_LWP_FREE @@ -592,7 +592,7 @@ void lwp_exit2(struct lwp *l) { - struct proc *p; + struct proc *p; KERNEL_LOCK(LK_EXCLUSIVE); /* diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_proc.c mult-netbsd-3.1/sys/kern/kern_proc.c --- NetBSD-3.1/sys/kern/kern_proc.c 2004-10-03 23:26:35.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_proc.c 2007-12-09 20:42:25.000000000 +0000 @@ -95,305 +95,249 @@ #include #include -/* - * Other process lists - */ - -struct proclist allproc; -struct proclist zombproc; /* resources have been freed */ +#include -/* - * Process list locking: - * - * We have two types of locks on the proclists: read locks and write - * locks. Read locks can be used in interrupt context, so while we - * hold the write lock, we must also block clock interrupts to - * lock out any scheduling changes that may happen in interrupt - * context. - * - * The proclist lock locks the following structures: - * - * allproc - * zombproc - * pid_table - */ -struct lock proclist_lock; - -/* - * pid to proc lookup is done by indexing the pid_table array. - * Since pid numbers are only allocated when an empty slot - * has been found, there is no need to search any lists ever. - * (an orphaned pgrp will lock the slot, a session will lock - * the pgrp with the same number.) - * If the table is too small it is reallocated with twice the - * previous size and the entries 'unzipped' into the two halves. - * A linked list of free entries is passed through the pt_proc - * field of 'free' items - set odd to be an invalid ptr. - */ - -struct pid_table { +struct pid_table +{ struct proc *pt_proc; struct pgrp *pt_pgrp; }; -#if 1 /* strongly typed cast - should be a noop */ -static __inline uint p2u(struct proc *p) { return (uint)(uintptr_t)p; } -#else -#define p2u(p) ((uint)p) -#endif -#define P_VALID(p) (!(p2u(p) & 1)) -#define P_NEXT(p) (p2u(p) >> 1) -#define P_FREE(pid) ((struct proc *)(uintptr_t)((pid) << 1 | 1)) - -#define INITIAL_PID_TABLE_SIZE (1 << 5) -static struct pid_table *pid_table; -static uint pid_tbl_mask = INITIAL_PID_TABLE_SIZE - 1; -static uint pid_alloc_lim; /* max we allocate before growing table */ -static uint pid_alloc_cnt; /* number of allocated pids */ - -/* links through free slots - never empty! */ -static uint next_free_pt, last_free_pt; -static pid_t pid_max = PID_MAX; /* largest value we allocate */ - -POOL_INIT(proc_pool, sizeof(struct proc), 0, 0, 0, "procpl", - &pool_allocator_nointr); -POOL_INIT(lwp_pool, sizeof(struct lwp), 0, 0, 0, "lwppl", - &pool_allocator_nointr); -POOL_INIT(lwp_uc_pool, sizeof(ucontext_t), 0, 0, 0, "lwpucpl", - &pool_allocator_nointr); -POOL_INIT(pgrp_pool, sizeof(struct pgrp), 0, 0, 0, "pgrppl", - &pool_allocator_nointr); -POOL_INIT(pcred_pool, sizeof(struct pcred), 0, 0, 0, "pcredpl", - &pool_allocator_nointr); -POOL_INIT(plimit_pool, sizeof(struct plimit), 0, 0, 0, "plimitpl", - &pool_allocator_nointr); -POOL_INIT(pstats_pool, sizeof(struct pstats), 0, 0, 0, "pstatspl", - &pool_allocator_nointr); -POOL_INIT(rusage_pool, sizeof(struct rusage), 0, 0, 0, "rusgepl", - &pool_allocator_nointr); -POOL_INIT(ras_pool, sizeof(struct ras), 0, 0, 0, "raspl", - &pool_allocator_nointr); -POOL_INIT(sadata_pool, sizeof(struct sadata), 0, 0, 0, "sadatapl", - &pool_allocator_nointr); -POOL_INIT(saupcall_pool, sizeof(struct sadata_upcall), 0, 0, 0, "saupcpl", - &pool_allocator_nointr); -POOL_INIT(sastack_pool, sizeof(struct sastack), 0, 0, 0, "sastackpl", - &pool_allocator_nointr); -POOL_INIT(savp_pool, sizeof(struct sadata_vp), 0, 0, 0, "savppl", - &pool_allocator_nointr); -POOL_INIT(ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl", - &pool_allocator_nointr); -POOL_INIT(session_pool, sizeof(struct session), 0, 0, 0, "sessionpl", - &pool_allocator_nointr); + +struct inst_proc +{ + uint pid_alloc_lim; /* XXX */ + uint pid_alloc_cnt; /* XXX */ + struct pid_table *pid_table; /* Master table of processes. */ + uint pid_tbl_mask; /* XXX */ + uint next_free_pt; /* XXX */ + uint last_free_pt; /* XXX */ + pid_t pid_max; /* Maximum pid. */ +}; + +static POOL_INIT(pcred_pool, sizeof(struct pcred), + 0, 0, 0, "pcredpl", &pool_allocator_nointr); + +static POOL_INIT(proc_pool, sizeof(struct proc), + 0, 0, 0, "procpl", &pool_allocator_nointr); + +static POOL_INIT(pgrp_pool, sizeof(struct pgrp), + 0, 0, 0, "pgrppl", &pool_allocator_nointr); + +static POOL_INIT(session_pool, sizeof(struct session), + 0, 0, 0, "sessionpl", &pool_allocator_nointr); + + +#define P_VALID(p) (!(p2u(p) & 1)) +#define P_NEXT(p) (p2u(p) >> 1) +#define P_FREE(pid) ((struct proc *)(uintptr_t)((pid) << 1 | 1)) +#define PID_INITTBL_SZ (1 << 5) MALLOC_DEFINE(M_EMULDATA, "emuldata", "Per-process emulation data"); MALLOC_DEFINE(M_PROC, "proc", "Proc structures"); MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures"); + /* - * The process list descriptors, used during pid allocation and - * by sysctl. No locking on this data structure is needed since - * it is completely static. + * A process group has become orphaned; if there are any stopped + * processes in the group, hang-up all process in that group. Call with + * proclist_lock held. */ -const struct proclist_desc proclists[] = { - { &allproc }, - { &zombproc }, - { NULL }, -}; - -static void orphanpg(struct pgrp *); -static void pg_delete(pid_t); +static void +orphanpg(struct pgrp *); /* - * Initialize global process hashing structures. + * Return a process group to the pool. */ -void -procinit(void) -{ - const struct proclist_desc *pd; - int i; -#define LINK_EMPTY ((PID_MAX + INITIAL_PID_TABLE_SIZE) & ~(INITIAL_PID_TABLE_SIZE - 1)) - - for (pd = proclists; pd->pd_list != NULL; pd++) - LIST_INIT(pd->pd_list); - - spinlockinit(&proclist_lock, "proclk", 0); - - pid_table = malloc(INITIAL_PID_TABLE_SIZE * sizeof *pid_table, - M_PROC, M_WAITOK); - /* Set free list running through table... - Preset 'use count' above PID_MAX so we allocate pid 1 next. */ - for (i = 0; i <= pid_tbl_mask; i++) { - pid_table[i].pt_proc = P_FREE(LINK_EMPTY + i + 1); - pid_table[i].pt_pgrp = 0; - } - /* slot 0 is just grabbed */ - next_free_pt = 1; - /* Need to fix last entry. */ - last_free_pt = pid_tbl_mask; - pid_table[last_free_pt].pt_proc = P_FREE(LINK_EMPTY); - /* point at which we grow table - to avoid reusing pids too often */ - pid_alloc_lim = pid_tbl_mask - 1; -#undef LINK_EMPTY - - LIST_INIT(&alllwp); - - uihashtbl = - hashinit(maxproc / 16, HASH_LIST, M_PROC, M_WAITOK, &uihash); -} +static void +pg_delete(struct inst *i, pid_t pgid); /* - * Acquire a read lock on the proclist. + * Free up the resources of a process group. */ -void -proclist_lock_read(void) -{ - int error; +static void +pg_free(struct inst *i, pid_t pgid); - error = spinlockmgr(&proclist_lock, LK_SHARED, NULL); -#ifdef DIAGNOSTIC - if (__predict_false(error != 0)) - panic("proclist_lock_read: failed to acquire lock"); -#endif -} +/* + * This is fairly self-explanatory. + */ +static void +expand_pid_table(struct inst *inst); /* - * Release a read lock on the proclist. + * Create a session with a valid parent (leader) process. */ -void -proclist_unlock_read(void) -{ +static void +sesscreate(struct proc *p, struct session *session); - (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); +#if 1 +static __inline uint +p2u(struct proc *p) +{ + return((uint)(uintptr_t)p); } +#else +# define p2u(p) ((uint)p) +#endif + -/* - * Acquire a write lock on the proclist. - */ int -proclist_lock_write(void) +inst_proc_alloc(inst_proc_t *p, int flags) { - int s, error; + struct inst_proc *i; + int j; - s = splclock(); - error = spinlockmgr(&proclist_lock, LK_EXCLUSIVE, NULL); -#ifdef DIAGNOSTIC - if (__predict_false(error != 0)) - panic("proclist_lock: failed to acquire lock"); -#endif - return (s); + KASSERT(p); + i = malloc(sizeof(struct inst_proc), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_proc)); + + i->pid_tbl_mask = PID_INITTBL_SZ - 1; + i->pid_max = PID_MAX; + i->pid_table = malloc(PID_INITTBL_SZ * + sizeof(*i->pid_table), M_PROC, flags); + if (NULL == i->pid_table) + return(0); + +#define LINK_EMPTY \ + ((PID_MAX + PID_INITTBL_SZ) & ~(PID_INITTBL_SZ - 1)) + + /* Set free list running through table... Preset 'use count' + * above PID_MAX so we allocate pid 1 next. */ + + for (j = 0; j <= i->pid_tbl_mask; j++) { + i->pid_table[j].pt_proc = P_FREE(LINK_EMPTY + j + 1); + i->pid_table[j].pt_pgrp = 0; + } + + i->next_free_pt = 1; + i->last_free_pt = i->pid_tbl_mask; + i->pid_table[i->last_free_pt].pt_proc = P_FREE(LINK_EMPTY); + i->pid_alloc_lim = i->pid_tbl_mask - 1; + +#undef LINK_EMPTY + *p = i; + return(1); } -/* - * Release a write lock on the proclist. - */ + void -proclist_unlock_write(int s) +inst_proc_free(inst_proc_t p) { - - (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); - splx(s); + KASSERT(p); + if (p->pid_table) + free(p->pid_table, M_PROC); } -/* - * Check that the specified process group is in the session of the - * specified process. - * Treats -ve ids as process ids. - * Used to validate TIOCSPGRP requests. - */ + int pgid_in_session(struct proc *p, pid_t pg_id) { - struct pgrp *pgrp; + struct pgrp *pgrp; + struct proc *p1; + + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); if (pg_id < 0) { - struct proc *p1 = pfind(-pg_id); + p1 = pfind(p->p_inst, -pg_id); if (p1 == NULL) - return EINVAL; + return(EINVAL); pgrp = p1->p_pgrp; } else { - pgrp = pgfind(pg_id); + pgrp = pgfind(p->p_inst, pg_id); if (pgrp == NULL) - return EINVAL; + return(EINVAL); } if (pgrp->pg_session != p->p_pgrp->pg_session) - return EPERM; - return 0; + return(EPERM); + return(0); } -/* - * Is p an inferior of q? - */ + int inferior(struct proc *p, struct proc *q) { + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + KASSERT(NULL != q); + KASSERT(NULL != q->p_inst); + + if (p->p_inst->i_uuid != q->p_inst->i_uuid) + return(0); for (; p != q; p = p->p_pptr) if (p->p_pid == 0) - return (0); - return (1); + return(0); + return(1); } -/* - * Locate a process by number - */ + struct proc * -p_find(pid_t pid, uint flags) +p_find(struct inst *i, pid_t pid, uint flags) { - struct proc *p; - char stat; + struct proc *p; + char stat; + + KASSERT(NULL != i); if (!(flags & PFIND_LOCKED)) - proclist_lock_read(); - p = pid_table[pid & pid_tbl_mask].pt_proc; + proclist_lock_read(i); + p = i->i_proc->pid_table[pid & i->i_proc->pid_tbl_mask].pt_proc; /* Only allow live processes to be found by pid. */ if (P_VALID(p) && p->p_pid == pid && ((stat = p->p_stat) == SACTIVE || stat == SSTOP || (stat == SZOMB && (flags & PFIND_ZOMBIE)))) { if (flags & PFIND_UNLOCK_OK) - proclist_unlock_read(); - return p; + proclist_unlock_read(i); + return(p); } if (flags & PFIND_UNLOCK_FAIL) - proclist_unlock_read(); - return NULL; + proclist_unlock_read(i); + return(NULL); } -/* - * Locate a process group by number - */ struct pgrp * -pg_find(pid_t pgid, uint flags) +pg_find(struct inst *i, pid_t pgid, uint flags) { - struct pgrp *pg; + struct pgrp *pg; + + KASSERT(NULL != i); if (!(flags & PFIND_LOCKED)) - proclist_lock_read(); - pg = pid_table[pgid & pid_tbl_mask].pt_pgrp; + proclist_lock_read(i); + pg = i->i_proc->pid_table[pgid & i->i_proc->pid_tbl_mask].pt_pgrp; + /* * Can't look up a pgrp that only exists because the session - * hasn't died yet (traditional) + * hasn't died yet (traditional). */ - if (pg == NULL || pg->pg_id != pgid || LIST_EMPTY(&pg->pg_members)) { + if (pg == NULL || pg->pg_id != pgid || + LIST_EMPTY(&pg->pg_members)) { if (flags & PFIND_UNLOCK_FAIL) - proclist_unlock_read(); - return NULL; + proclist_unlock_read(i); + return(NULL); } if (flags & PFIND_UNLOCK_OK) - proclist_unlock_read(); - return pg; + proclist_unlock_read(i); + return(pg); } -/* - * Set entry for process 0 - */ + void -proc0_insert(struct proc *p, struct lwp *l, struct pgrp *pgrp, - struct session *sess) +proc0_insert(struct proc *p, struct lwp *l, + struct pgrp *pgrp, struct session *sess) { - int s; + int s; + struct inst *i; + + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + + i = p->p_inst; simple_lock_init(&p->p_lock); LIST_INIT(&p->p_lwps); @@ -402,62 +346,63 @@ simple_lock_init(&p->p_sigctx.ps_silock); CIRCLEQ_INIT(&p->p_sigctx.ps_siginfo); - s = proclist_lock_write(); + s = proclist_lock_write(i); - pid_table[0].pt_proc = p; - LIST_INSERT_HEAD(&allproc, p, p_list); - LIST_INSERT_HEAD(&alllwp, l, l_list); + i->i_proc->pid_table[0].pt_proc = p; + LIST_INSERT_HEAD(&i->i_allproc, p, p_list); + LIST_INSERT_HEAD(&i->i_alllwp, l, l_list); p->p_pgrp = pgrp; - pid_table[0].pt_pgrp = pgrp; + i->i_proc->pid_table[0].pt_pgrp = pgrp; LIST_INIT(&pgrp->pg_members); LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); + sesscreate(p, sess); pgrp->pg_session = sess; - sess->s_count = 1; - sess->s_sid = 0; - sess->s_leader = p; - proclist_unlock_write(s); + proclist_unlock_write(i, s); } + static void -expand_pid_table(void) +expand_pid_table(struct inst *in) { - uint pt_size = pid_tbl_mask + 1; + uint pt_size; struct pid_table *n_pt, *new_pt; - struct proc *proc; - struct pgrp *pgrp; - int i; - int s; - pid_t pid; + struct proc *proc; + struct pgrp *pgrp; + int i, s; + pid_t pid; + + KASSERT(in); + + pt_size = in->i_proc->pid_tbl_mask + 1; + new_pt = malloc(pt_size * 2 * sizeof(*new_pt), + M_PROC, M_WAITOK); - new_pt = malloc(pt_size * 2 * sizeof *new_pt, M_PROC, M_WAITOK); - - s = proclist_lock_write(); - if (pt_size != pid_tbl_mask + 1) { + s = proclist_lock_write(in); + if (pt_size != in->i_proc->pid_tbl_mask + 1) { /* Another process beat us to it... */ - proclist_unlock_write(s); + proclist_unlock_write(in, s); FREE(new_pt, M_PROC); return; } /* - * Copy entries from old table into new one. - * If 'pid' is 'odd' we need to place in the upper half, - * even pid's to the lower half. - * Free items stay in the low half so we don't have to - * fixup the reference to them. - * We stuff free items on the front of the freelist - * because we can't write to unmodified entries. - * Processing the table backwards maintains a semblance - * of issueing pid numbers that increase with time. + * Copy entries from old table into new one. If 'pid' is 'odd' + * we need to place in the upper half, even pid's to the lower + * half. Free items stay in the low half so we don't have to + * fixup the reference to them. We stuff free items on the + * front of the freelist because we can't write to unmodified + * entries. Processing the table backwards maintains a + * semblance of issueing pid numbers that increase with time. */ i = pt_size - 1; n_pt = new_pt + i; + for (; ; i--, n_pt--) { - proc = pid_table[i].pt_proc; - pgrp = pid_table[i].pt_pgrp; + proc = in->i_proc->pid_table[i].pt_proc; + pgrp = in->i_proc->pid_table[i].pt_pgrp; if (!P_VALID(proc)) { /* Up 'use count' so that link is valid */ pid = (P_NEXT(proc) + pt_size) & ~pt_size; @@ -472,167 +417,185 @@ n_pt[pid & pt_size].pt_pgrp = pgrp; /* Put other piece on start of free list */ - pid = (pid ^ pt_size) & ~pid_tbl_mask; - n_pt[pid & pt_size].pt_proc = - P_FREE((pid & ~pt_size) | next_free_pt); + pid = (pid ^ pt_size) & ~in->i_proc->pid_tbl_mask; + n_pt[pid & pt_size].pt_proc = P_FREE((pid & ~pt_size) + | in->i_proc->next_free_pt); n_pt[pid & pt_size].pt_pgrp = 0; - next_free_pt = i | (pid & pt_size); + in->i_proc->next_free_pt = i | (pid & pt_size); if (i == 0) break; } /* Switch tables */ - n_pt = pid_table; - pid_table = new_pt; - pid_tbl_mask = pt_size * 2 - 1; + n_pt = in->i_proc->pid_table; + in->i_proc->pid_table = new_pt; + in->i_proc->pid_tbl_mask = pt_size * 2 - 1; /* * pid_max starts as PID_MAX (= 30000), once we have 16384 * allocated pids we need it to be larger! */ - if (pid_tbl_mask > PID_MAX) { - pid_max = pid_tbl_mask * 2 + 1; - pid_alloc_lim |= pid_alloc_lim << 1; - } else - pid_alloc_lim <<= 1; /* doubles number of free slots... */ - - proclist_unlock_write(s); + if (in->i_proc->pid_tbl_mask > PID_MAX) { + in->i_proc->pid_max = in->i_proc->pid_tbl_mask * 2 + 1; + in->i_proc->pid_alloc_lim |= in->i_proc->pid_alloc_lim << 1; + } else /* double number of free slots... */ + in->i_proc->pid_alloc_lim <<= 1; + + proclist_unlock_write(in, s); FREE(n_pt, M_PROC); } + struct proc * -proc_alloc(void) +proc_alloc(struct inst *i) { - struct proc *p; - int s; - int nxt; - pid_t pid; + struct proc *p; + int s, nxt; + pid_t pid; struct pid_table *pt; + KASSERT(i); + p = pool_get(&proc_pool, PR_WAITOK); - p->p_stat = SIDL; /* protect against others */ + p->p_stat = SIDL; /* allocate next free pid */ - for (;;expand_pid_table()) { - if (__predict_false(pid_alloc_cnt >= pid_alloc_lim)) + for (;;expand_pid_table(i)) { + if (__predict_false(i->i_proc->pid_alloc_cnt >= + i->i_proc->pid_alloc_lim)) /* ensure pids cycle through 2000+ values */ continue; - s = proclist_lock_write(); - pt = &pid_table[next_free_pt]; + s = proclist_lock_write(i); + pt = &i->i_proc->pid_table[i->i_proc->next_free_pt]; #ifdef DIAGNOSTIC if (__predict_false(P_VALID(pt->pt_proc) || pt->pt_pgrp)) panic("proc_alloc: slot busy"); #endif nxt = P_NEXT(pt->pt_proc); - if (nxt & pid_tbl_mask) + if (nxt & i->i_proc->pid_tbl_mask) break; /* Table full - expand (NB last entry not used....) */ - proclist_unlock_write(s); + proclist_unlock_write(i, s); } /* pid is 'saved use count' + 'size' + entry */ - pid = (nxt & ~pid_tbl_mask) + pid_tbl_mask + 1 + next_free_pt; - if ((uint)pid > (uint)pid_max) - pid &= pid_tbl_mask; + pid = (nxt & ~i->i_proc->pid_tbl_mask) + + i->i_proc->pid_tbl_mask + 1 + i->i_proc->next_free_pt; + if ((uint)pid > (uint)i->i_proc->pid_max) + pid &= i->i_proc->pid_tbl_mask; p->p_pid = pid; - next_free_pt = nxt & pid_tbl_mask; + i->i_proc->next_free_pt = nxt & i->i_proc->pid_tbl_mask; /* Grab table slot */ pt->pt_proc = p; - pid_alloc_cnt++; + i->i_proc->pid_alloc_cnt++; - proclist_unlock_write(s); + proclist_unlock_write(i, s); - return p; + return(p); } -/* - * Free last resources of a process - called from proc_free (in kern_exit.c) - */ + void -proc_free_mem(struct proc *p) +proc_free_mem(struct inst *i, struct proc *p) { - int s; - pid_t pid = p->p_pid; + int s; + pid_t pid; struct pid_table *pt; - s = proclist_lock_write(); + KASSERT(p); + KASSERT(i); + + pid = p->p_pid; + + s = proclist_lock_write(i); - pt = &pid_table[pid & pid_tbl_mask]; + pt = &i->i_proc->pid_table[pid & i->i_proc->pid_tbl_mask]; #ifdef DIAGNOSTIC if (__predict_false(pt->pt_proc != p)) panic("proc_free: pid_table mismatch, pid %x, proc %p", pid, p); #endif /* save pid use count in slot */ - pt->pt_proc = P_FREE(pid & ~pid_tbl_mask); + pt->pt_proc = P_FREE(pid & ~i->i_proc->pid_tbl_mask); if (pt->pt_pgrp == NULL) { /* link last freed entry onto ours */ - pid &= pid_tbl_mask; - pt = &pid_table[last_free_pt]; + pid &= i->i_proc->pid_tbl_mask; + pt = &i->i_proc->pid_table[i->i_proc->last_free_pt]; pt->pt_proc = P_FREE(P_NEXT(pt->pt_proc) | pid); - last_free_pt = pid; - pid_alloc_cnt--; + i->i_proc->last_free_pt = pid; + i->i_proc->pid_alloc_cnt--; } - nprocs--; - proclist_unlock_write(s); - + i->i_nprocs--; + proclist_unlock_write(i, s); pool_put(&proc_pool, p); + + inst_release(i); } -/* - * Move p to a new or existing process group (and session) - * - * If we are creating a new pgrp, the pgid should equal - * the calling process' pid. - * If is only valid to enter a process group that is in the session - * of the process. - * Also mksess should only be set if we are creating a process group - * - * Only called from sys_setsid, sys_setpgid/sys_setpgrp and the - * SYSV setpgrp support for hpux == enterpgrp(curproc, curproc->p_pid) - */ + int enterpgrp(struct proc *p, pid_t pgid, int mksess) { - struct pgrp *new_pgrp, *pgrp; - struct session *sess; - struct proc *curp = curproc; - pid_t pid = p->p_pid; - int rval; - int s; - pid_t pg_id = NO_PGID; - - /* Allocate data areas we might need before doing any validity checks */ - proclist_lock_read(); /* Because pid_table might change */ - if (pid_table[pgid & pid_tbl_mask].pt_pgrp == 0) { - proclist_unlock_read(); + struct pgrp *new_pgrp, *pgrp; + struct session *sess; + struct inst *i; + struct proc *curp; + pid_t pid; + int rval, s; + pid_t pg_id = NO_PGID; + + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + + curp = curproc; + i = p->p_inst; + pid = p->p_pid; + + KASSERT(NULL != curp->p_inst); + + if (i->i_uuid != curp->p_inst->i_uuid) + return(ESRCH); + + /* + * Allocate data areas we might need before doing any validity + * checks + */ + + proclist_lock_read(i); + + if (i->i_proc->pid_table[pgid & i->i_proc->pid_tbl_mask].pt_pgrp == 0) { + proclist_unlock_read(i); new_pgrp = pool_get(&pgrp_pool, PR_WAITOK); } else { - proclist_unlock_read(); + proclist_unlock_read(i); new_pgrp = NULL; } + if (mksess) sess = pool_get(&session_pool, M_WAITOK); else sess = NULL; - s = proclist_lock_write(); + s = proclist_lock_write(i); rval = EPERM; /* most common error (to save typing) */ /* Check pgrp exists or can be created */ - pgrp = pid_table[pgid & pid_tbl_mask].pt_pgrp; + + pgrp = i->i_proc->pid_table[pgid & i->i_proc->pid_tbl_mask].pt_pgrp; if (pgrp != NULL && pgrp->pg_id != pgid) goto done; - /* Can only set another process under restricted circumstances. */ + /* Can set another process under restricted circumstances. */ + if (p != curp) { /* must exist and be one of our children... */ - if (p != pid_table[pid & pid_tbl_mask].pt_proc - || !inferior(p, curp)) { + if (p != i->i_proc->pid_table[pid & + i->i_proc->pid_tbl_mask].pt_proc || + ! inferior(p, curp)) { rval = ESRCH; goto done; } @@ -686,14 +649,12 @@ pgrp = new_pgrp; new_pgrp = 0; if (sess != NULL) { - sess->s_sid = p->p_pid; - sess->s_leader = p; - sess->s_count = 1; + sesscreate(p, sess); sess->s_ttyvp = NULL; sess->s_ttyp = NULL; sess->s_flags = p->p_session->s_flags & ~S_LOGIN_SET; memcpy(sess->s_login, p->p_session->s_login, - sizeof(sess->s_login)); + sizeof(sess->s_login)); p->p_flag &= ~P_CONTROLT; } else { sess = p->p_pgrp->pg_session; @@ -705,24 +666,27 @@ pgrp->pg_id = pgid; LIST_INIT(&pgrp->pg_members); #ifdef DIAGNOSTIC - if (__predict_false(pid_table[pgid & pid_tbl_mask].pt_pgrp)) + if (__predict_false(i->i_proc->pid_table[pgid & + i->i_proc->pid_tbl_mask].pt_pgrp)) panic("enterpgrp: pgrp table slot in use"); if (__predict_false(mksess && p != curp)) panic("enterpgrp: mksession and p != curproc"); #endif - pid_table[pgid & pid_tbl_mask].pt_pgrp = pgrp; + i->i_proc->pid_table[pgid & i->i_proc->pid_tbl_mask].pt_pgrp = pgrp; pgrp->pg_jobc = 0; } /* - * Adjust eligibility of affected pgrps to participate in job control. - * Increment eligibility counts before decrementing, otherwise we - * could reach 0 spuriously during the first call. + * Adjust eligibility of affected pgrps to participate in job + * control. Increment eligibility counts before decrementing, + * otherwise we could reach 0 spuriously during the first call. */ + fixjobc(p, pgrp, 1); fixjobc(p, p->p_pgrp, 0); /* Move process to requested group */ + LIST_REMOVE(p, p_pglist); if (LIST_EMPTY(&p->p_pgrp->pg_members)) /* defer delete until we've dumped the lock */ @@ -731,94 +695,103 @@ LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); done: - proclist_unlock_write(s); - if (sess != NULL) + proclist_unlock_write(i, s); + if (sess != NULL) pool_put(&session_pool, sess); - if (new_pgrp != NULL) + if (new_pgrp != NULL) pool_put(&pgrp_pool, new_pgrp); if (pg_id != NO_PGID) - pg_delete(pg_id); + pg_delete(i, pg_id); #ifdef DEBUG_PGRP if (__predict_false(rval)) printf("enterpgrp(%d,%d,%d), curproc %d, rval %d\n", pid, pgid, mksess, curp->p_pid, rval); #endif - return rval; + return(rval); } -/* - * remove process from process group - */ + int leavepgrp(struct proc *p) { - int s; - struct pgrp *pgrp; - pid_t pg_id; + int s; + struct pgrp *pgrp; + pid_t pg_id; + + KASSERT(p); + KASSERT(p->p_inst); + + s = proclist_lock_write(p->p_inst); - s = proclist_lock_write(); pgrp = p->p_pgrp; LIST_REMOVE(p, p_pglist); p->p_pgrp = 0; pg_id = LIST_EMPTY(&pgrp->pg_members) ? pgrp->pg_id : NO_PGID; - proclist_unlock_write(s); + proclist_unlock_write(p->p_inst, s); if (pg_id != NO_PGID) - pg_delete(pg_id); - return 0; + pg_delete(p->p_inst, pg_id); + return(0); } + static void -pg_free(pid_t pg_id) +pg_free(struct inst *i, pid_t pg_id) { - struct pgrp *pgrp; + struct pgrp *pgrp; struct pid_table *pt; - int s; + int s; + + KASSERT(NULL != i); - s = proclist_lock_write(); - pt = &pid_table[pg_id & pid_tbl_mask]; + s = proclist_lock_write(i); + pt = &i->i_proc->pid_table[pg_id & i->i_proc->pid_tbl_mask]; pgrp = pt->pt_pgrp; #ifdef DIAGNOSTIC if (__predict_false(!pgrp || pgrp->pg_id != pg_id || !LIST_EMPTY(&pgrp->pg_members))) - panic("pg_free: process group absent or has members"); + panic("pg_free: process group absent or has members " + "%p, %d != %d, %d", + pgrp, pgrp->pg_id, pg_id, + LIST_EMPTY(&pgrp->pg_members)); #endif pt->pt_pgrp = 0; if (!P_VALID(pt->pt_proc)) { /* orphaned pgrp, put slot onto free list */ #ifdef DIAGNOSTIC - if (__predict_false(P_NEXT(pt->pt_proc) & pid_tbl_mask)) + if (__predict_false(P_NEXT(pt->pt_proc) & + i->i_proc->pid_tbl_mask)) panic("pg_free: process slot on free list"); #endif - pg_id &= pid_tbl_mask; - pt = &pid_table[last_free_pt]; + pg_id &= i->i_proc->pid_tbl_mask; + pt = &i->i_proc->pid_table[i->i_proc->last_free_pt]; pt->pt_proc = P_FREE(P_NEXT(pt->pt_proc) | pg_id); - last_free_pt = pg_id; - pid_alloc_cnt--; + i->i_proc->last_free_pt = pg_id; + i->i_proc->pid_alloc_cnt--; } - proclist_unlock_write(s); - + proclist_unlock_write(i, s); pool_put(&pgrp_pool, pgrp); } -/* - * delete a process group - */ + static void -pg_delete(pid_t pg_id) +pg_delete(struct inst *i, pid_t pg_id) { - struct pgrp *pgrp; - struct tty *ttyp; - struct session *ss; - int s, is_pgrp_leader; + struct pgrp *pgrp; + struct tty *ttyp; + struct session *ss; + int s, is_pgrp_leader; + + KASSERT(i); + + s = proclist_lock_write(i); + pgrp = i->i_proc->pid_table[pg_id & i->i_proc->pid_tbl_mask].pt_pgrp; - s = proclist_lock_write(); - pgrp = pid_table[pg_id & pid_tbl_mask].pt_pgrp; if (pgrp == NULL || pgrp->pg_id != pg_id || !LIST_EMPTY(&pgrp->pg_members)) { - proclist_unlock_write(s); + proclist_unlock_write(i, s); return; } @@ -835,66 +808,80 @@ } /* - * The leading process group in a session is freed - * by sessdelete() if last reference. + * The leading process group in a session is freed by + * sessdelete() if last reference. */ is_pgrp_leader = (ss->s_sid == pgrp->pg_id); - proclist_unlock_write(s); + proclist_unlock_write(i, s); SESSRELE(ss); if (is_pgrp_leader) return; + pg_free(i, pg_id); +} + + +static void +sesscreate(struct proc *p, struct session *sess) +{ + KASSERT(p); + KASSERT(sess); + KASSERT(p->p_inst); - pg_free(pg_id); + /* + * Note that the session also holds a reference to the instance, + * as a session is deleted only when the last process is already + * deleted, and we need a context to put the reaped session data + * back into. + */ + sess->s_inst = p->p_inst; + sess->s_count = 1; + sess->s_sid = p->p_pid; + sess->s_leader = p; + p->p_inst->i_nsess++; } -/* - * Delete session - called from SESSRELE when s_count becomes zero. - */ + void sessdelete(struct session *ss) { /* - * We keep the pgrp with the same id as the session in - * order to stop a process being given the same pid. - * Since the pgrp holds a reference to the session, it - * must be a 'zombie' pgrp by now. + * We keep the pgrp with the same id as the session in order to + * stop a process being given the same pid. Since the pgrp + * holds a reference to the session, it must be a 'zombie' pgrp + * by now. */ - - pg_free(ss->s_sid); - + pg_free(ss->s_inst, ss->s_sid); + ss->s_inst->i_nsess--; pool_put(&session_pool, ss); } -/* - * Adjust pgrp jobc counters when specified process changes process group. - * We count the number of processes in each process group that "qualify" - * the group for terminal job control (those with a parent in a different - * process group of the same session). If that count reaches zero, the - * process group becomes orphaned. Check both the specified process' - * process group and that of its children. - * entering == 0 => p is leaving specified group. - * entering == 1 => p is entering specified group. - * - * Call with proclist_lock held. - */ + void fixjobc(struct proc *p, struct pgrp *pgrp, int entering) { - struct pgrp *hispgrp; - struct session *mysession = pgrp->pg_session; - struct proc *child; + struct pgrp *hispgrp; + struct session *mysession; + struct proc *child; + + KASSERT(NULL != p); + KASSERT(NULL != pgrp); + + mysession = pgrp->pg_session; /* * Check p's parent to see whether p qualifies its own process * group; if so, adjust count for p's process group. */ - hispgrp = p->p_pptr->p_pgrp; - if (hispgrp != pgrp && hispgrp->pg_session == mysession) { - if (entering) - pgrp->pg_jobc++; - else if (--pgrp->pg_jobc == 0) - orphanpg(pgrp); + if (NULL != p->p_pptr) { + hispgrp = p->p_pptr->p_pgrp; + if (hispgrp != pgrp && + hispgrp->pg_session == mysession) { + if (entering) + pgrp->pg_jobc++; + else if (--pgrp->pg_jobc == 0) + orphanpg(pgrp); + } } /* @@ -914,17 +901,13 @@ } } -/* - * A process group has become orphaned; - * if there are any stopped processes in the group, - * hang-up all process in that group. - * - * Call with proclist_lock held. - */ + static void orphanpg(struct pgrp *pg) { - struct proc *p; + struct proc *p; + + KASSERT(NULL != pg); LIST_FOREACH(p, &pg->pg_members, p_pglist) { if (p->p_stat == SSTOP) { @@ -937,12 +920,15 @@ } } -/* mark process as suid/sgid, reset some values to defaults */ + void p_sugid(struct proc *p) { - struct plimit *lim; - char *cn; + struct plimit *lim; + char *cn; + + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); p->p_flag |= P_SUGID; /* reset what needs to be reset in plimit */ @@ -963,7 +949,12 @@ } } -#ifdef DDB + +/* + * FIXME - the following section assumes a global context, which is no + * longer correct. Byeeeee! + */ +#if 0 /* Was "if DDB" */ #include void pidtbl_dump(void); void @@ -975,9 +966,9 @@ int id; db_printf("pid table %p size %x, next %x, last %x\n", - pid_table, pid_tbl_mask+1, + pid_table, PID_TBL_MASK+1, next_free_pt, last_free_pt); - for (pt = pid_table, id = 0; id <= pid_tbl_mask; id++, pt++) { + for (pt = pid_table, id = 0; id <= PID_TBL_MASK; id++, pt++) { p = pt->pt_proc; if (!P_VALID(p) && !pt->pt_pgrp) continue; @@ -987,8 +978,8 @@ p, p->p_pid, p->p_pid, p->p_comm); else db_printf("next %x use %x\n", - P_NEXT(p) & pid_tbl_mask, - P_NEXT(p) & ~pid_tbl_mask); + P_NEXT(p) & PID_TBL_MASK, + P_NEXT(p) & ~PID_TBL_MASK); if ((pgrp = pt->pt_pgrp)) { db_printf("\tsession %p, sid %d, count %d, login %s\n", pgrp->pg_session, pgrp->pg_session->s_sid, @@ -1085,6 +1076,12 @@ } #endif /* KSTACK_CHECK_MAGIC */ + +/* + * FIXME: (or not) This is getting removed along with procfs, which + * doesn't play nicely with instances. Byeeee! + */ +#if 0 /* XXX shouldn't be here */ #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) #define PROCLIST_ASSERT_LOCKED_READ() \ @@ -1121,3 +1118,21 @@ return ret; } +#endif + + +void +pcred_free(struct pcred *p) +{ + pool_put(&pcred_pool, p); +} + + +struct pcred * +pcred_alloc(void) +{ + struct pcred *pc; + pc = pool_get(&pcred_pool, PR_WAITOK); + memset(pc, 0, sizeof(struct pcred)); + return(pc); +} diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_prot.c mult-netbsd-3.1/sys/kern/kern_prot.c --- NetBSD-3.1/sys/kern/kern_prot.c 2004-05-04 22:27:28.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_prot.c 2007-11-23 10:17:19.000000000 +0000 @@ -60,6 +60,8 @@ #include #include +#include + POOL_INIT(cred_pool, sizeof(struct ucred), 0, 0, 0, "credpl", &pool_allocator_nointr); @@ -86,8 +88,11 @@ { struct proc *p = l->l_proc; + KASSERT(l); + KASSERT(p); + retval[0] = p->p_pid; - retval[1] = p->p_pptr->p_pid; + retval[1] = p->p_pptr ? p->p_pptr->p_pid : 0; return (0); } @@ -97,7 +102,7 @@ { struct proc *p = l->l_proc; - *retval = p->p_pptr->p_pid; + *retval = p->p_pptr ? p->p_pptr->p_pid : 0; return (0); } @@ -123,9 +128,12 @@ } */ *uap = v; struct proc *p = l->l_proc; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + if (SCARG(uap, pid) == 0) goto found; - if ((p = pfind(SCARG(uap, pid))) == 0) + if ((p = pfind(p->p_inst, SCARG(uap, pid))) == 0) return (ESRCH); found: *retval = p->p_session->s_sid; @@ -140,9 +148,12 @@ } */ *uap = v; struct proc *p = l->l_proc; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + if (SCARG(uap, pid) == 0) goto found; - if ((p = pfind(SCARG(uap, pid))) == 0) + if ((p = pfind(p->p_inst, SCARG(uap, pid))) == 0) return (ESRCH); found: *retval = p->p_pgid; @@ -251,7 +262,10 @@ { struct proc *p = l->l_proc; - if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + + if (p->p_pgid == p->p_pid || pgfind(p->p_inst, p->p_pid)) { return (EPERM); } else { (void)enterpgrp(p, p->p_pid, 1); @@ -287,12 +301,15 @@ struct proc *curp = l->l_proc; struct proc *targp; /* target process */ + KASSERT(NULL != curp); + KASSERT(NULL != curp->p_inst); + if (SCARG(uap, pgid) < 0) return EINVAL; /* XXX MP - there is a horrid race here with targp exiting! */ if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) { - targp = pfind(SCARG(uap, pid)); + targp = pfind(curp->p_inst, SCARG(uap, pid)); if (targp == NULL) return ESRCH; } else @@ -313,10 +330,14 @@ int do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags) { - int error; - struct proc *p = l->l_proc; - struct pcred *pcred = p->p_cred; - struct ucred *cred = pcred->pc_ucred; + int error; + struct proc *p = l->l_proc; + struct pcred *pcred = p->p_cred; + struct ucred *cred = pcred->pc_ucred; + struct inst *i; + + KASSERT(NULL != p->p_inst); + i = p->p_inst; /* Superuser can do anything it wants to.... */ error = suser(cred, &p->p_acflag); @@ -347,8 +368,8 @@ /* The pcred structure is not actually shared... */ if (r != -1 && r != pcred->p_ruid) { /* Update count of processes for this user */ - (void)chgproccnt(pcred->p_ruid, -1); - (void)chgproccnt(r, 1); + (void)chgproccnt(i, pcred->p_ruid, -1); + (void)chgproccnt(i, r, 1); pcred->p_ruid = r; } if (sv != -1) @@ -585,6 +606,9 @@ const gid_t *gp; const gid_t *egp; + KASSERT(NULL != cred); + KASSERT(NULL != cred->cr_inst); + egp = &(cred->cr_groups[cred->cr_ngroups]); for (gp = cred->cr_groups; gp < egp; gp++) if (*gp == gid) @@ -614,15 +638,22 @@ * Allocate a zeroed cred structure. */ struct ucred * -crget(void) +crget(struct inst *i) { struct ucred *cr; + KASSERT(i); + cr = pool_get(&cred_pool, PR_WAITOK); - memset(cr, 0, sizeof(*cr)); + memset(cr, 0, sizeof(struct ucred)); simple_lock_init(&cr->cr_lock); cr->cr_ref = 1; - return (cr); + cr->cr_inst = i; + inst_hold(i); + + /* FIXME - instance - locking */ + i->i_ncreds++; + return(cr); } /* @@ -634,11 +665,18 @@ { int n; + KASSERT(cr); + KASSERT(cr->cr_inst); + simple_lock(&cr->cr_lock); n = --cr->cr_ref; simple_unlock(&cr->cr_lock); - if (n == 0) - pool_put(&cred_pool, cr); + if (n > 0) + return; + + cr->cr_inst->i_ncreds--; + inst_release(cr->cr_inst); + pool_put(&cred_pool, cr); } /* @@ -661,16 +699,37 @@ { struct ucred *newcr; + KASSERT(cr); + KASSERT(cr->cr_inst); + if (cr->cr_ref == 1) return (cr); - newcr = crget(); + newcr = crget(cr->cr_inst); memcpy(&newcr->cr_startcopy, &cr->cr_startcopy, sizeof(struct ucred) - offsetof(struct ucred, cr_startcopy)); + crfree(cr); return (newcr); } + +/* + * Dup cred struct to a new held one, but inherit only the instance. + */ +struct ucred * +crdupinst(const struct ucred *cr) +{ + struct ucred *newcr; + + KASSERT(cr); + KASSERT(cr->cr_inst); + + newcr = crget(cr->cr_inst); + + return (newcr); +} + /* * Dup cred struct to a new held one. */ @@ -679,9 +738,13 @@ { struct ucred *newcr; - newcr = crget(); + KASSERT(cr); + KASSERT(cr->cr_inst); + + newcr = crget(cr->cr_inst); memcpy(&newcr->cr_startcopy, &cr->cr_startcopy, sizeof(struct ucred) - offsetof(struct ucred, cr_startcopy)); + return (newcr); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_ras.c mult-netbsd-3.1/sys/kern/kern_ras.c --- NetBSD-3.1/sys/kern/kern_ras.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_ras.c 2007-11-13 18:31:33.000000000 +0000 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,10 @@ #define MAX_RAS_PER_PROC 16 + +static POOL_INIT(ras_pool, sizeof(struct ras), + 0, 0, 0, "raspl", &pool_allocator_nointr); + u_int ras_per_proc = MAX_RAS_PER_PROC; #ifdef DEBUG @@ -64,8 +69,13 @@ #define DPRINTF(x) /* nothing */ #endif -int ras_install(struct proc *, caddr_t, size_t); -int ras_purge(struct proc *, caddr_t, size_t); + +int +ras_install(struct proc *, caddr_t, size_t); + +int +ras_purge(struct proc *, caddr_t, size_t); + /* * Check the specified address to see if it is within the diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_resource.c mult-netbsd-3.1/sys/kern/kern_resource.c --- NetBSD-3.1/sys/kern/kern_resource.c 2005-09-18 21:09:50.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_resource.c 2007-11-23 10:17:19.000000000 +0000 @@ -53,38 +53,88 @@ #include #include +#include + #include + +struct inst_res +{ + struct uihashhead *uihashtbl; + u_long uihash; +}; + +static POOL_INIT(plimit_pool, sizeof(struct plimit), + 0, 0, 0, "plimitpl", &pool_allocator_nointr); + +static POOL_INIT(pstats_pool, sizeof(struct pstats), + 0, 0, 0, "pststpl", &pool_allocator_nointr); + + +#define UIHASH(res, uid) \ + (&(res)->uihashtbl[(uid) & (res)->uihash]) + /* - * Maximum process data and stack limits. - * They are variables so they are patchable. + * Maximum process data and stack limits. They are variables so they + * are patchable. These don't change, so they're save not to put into + * the instance context. */ -rlim_t maxdmap = MAXDSIZ; -rlim_t maxsmap = MAXSSIZ; +rlim_t maxdmap = MAXDSIZ; +rlim_t maxsmap = MAXSSIZ; + +static void freeuidinfo(struct uidinfo *); +static struct uidinfo *allocuidinfo(struct inst *i, uid_t uid); +static struct uidinfo *getuidinfo(struct inst *i, uid_t uid); + + +int +inst_res_alloc(inst_res_t *p, int flags) +{ + struct inst_res *i; + + KASSERT(p); + + i = malloc(sizeof(struct inst_res), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_res)); + + i->uihash = 0; + i->uihashtbl = hashinit(maxproc / 16, HASH_LIST, + M_INST, flags, &i->uihash); + *p = i; + return(1); +} + -struct uihashhead *uihashtbl; -u_long uihash; /* size of hash table - 1 */ +void +inst_res_free(inst_res_t p) +{ + KASSERT(p); + if (p->uihashtbl) + free(p->uihashtbl, M_INST); + free(p, M_INST); +} -static struct uidinfo *getuidinfo(uid_t); -static void freeuidinfo(struct uidinfo *); -static struct uidinfo *allocuidinfo(uid_t); /* * Resource controls and accounting. */ - int -sys_getpriority(l, v, retval) - struct lwp *l; - void *v; - register_t *retval; +sys_getpriority(struct lwp *l, void *v, register_t *retval) { struct sys_getpriority_args /* { syscallarg(int) which; syscallarg(id_t) who; } */ *uap = v; - struct proc *curp = l->l_proc, *p; - int low = NZERO + PRIO_MAX + 1; + struct proc *curp, *p; + int low; + + curp = l->l_proc; + low = NZERO + PRIO_MAX + 1; + + KASSERT(curp); + KASSERT(curp->p_inst); switch (SCARG(uap, which)) { @@ -92,7 +142,7 @@ if (SCARG(uap, who) == 0) p = curp; else - p = pfind(SCARG(uap, who)); + p = pfind(curp->p_inst, SCARG(uap, who)); if (p == 0) break; low = p->p_nice; @@ -103,7 +153,7 @@ if (SCARG(uap, who) == 0) pg = curp->p_pgrp; - else if ((pg = pgfind(SCARG(uap, who))) == NULL) + else if ((pg = pgfind(curp->p_inst, SCARG(uap, who))) == NULL) break; LIST_FOREACH(p, &pg->pg_members, p_pglist) { if (p->p_nice < low) @@ -115,13 +165,13 @@ case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + proclist_lock_read(curp->p_inst); + PROCLIST_FOREACH(p, &curp->p_inst->i_allproc) { if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who) && p->p_nice < low) low = p->p_nice; } - proclist_unlock_read(); + proclist_unlock_read(curp->p_inst); break; default: @@ -133,6 +183,7 @@ return (0); } + /* ARGSUSED */ int sys_setpriority(l, v, retval) @@ -148,13 +199,16 @@ struct proc *curp = l->l_proc, *p; int found = 0, error = 0; + KASSERT(curp); + KASSERT(curp->p_inst); + switch (SCARG(uap, which)) { case PRIO_PROCESS: if (SCARG(uap, who) == 0) p = curp; else - p = pfind(SCARG(uap, who)); + p = pfind(curp->p_inst, SCARG(uap, who)); if (p == 0) break; error = donice(curp, p, SCARG(uap, prio)); @@ -166,7 +220,7 @@ if (SCARG(uap, who) == 0) pg = curp->p_pgrp; - else if ((pg = pgfind(SCARG(uap, who))) == NULL) + else if ((pg = pgfind(curp->p_inst, SCARG(uap, who))) == NULL) break; LIST_FOREACH(p, &pg->pg_members, p_pglist) { error = donice(curp, p, SCARG(uap, prio)); @@ -178,14 +232,14 @@ case PRIO_USER: if (SCARG(uap, who) == 0) SCARG(uap, who) = curp->p_ucred->cr_uid; - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + proclist_lock_read(curp->p_inst); + PROCLIST_FOREACH(p, &curp->p_inst->i_allproc) { if (p->p_ucred->cr_uid == (uid_t) SCARG(uap, who)) { error = donice(curp, p, SCARG(uap, prio)); found++; } } - proclist_unlock_read(); + proclist_unlock_read(curp->p_inst); break; default: @@ -196,13 +250,14 @@ return (error); } + int -donice(curp, chgp, n) - struct proc *curp, *chgp; - int n; +donice(struct proc *curp, struct proc *chgp, int n) { - struct pcred *pcred = curp->p_cred; - int s; + struct pcred *pcred; + int s; + + pcred = curp->p_cred; if (pcred->pc_ucred->cr_uid && pcred->p_ruid && pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && @@ -222,21 +277,22 @@ return (0); } + /* ARGSUSED */ int -sys_setrlimit(l, v, retval) - struct lwp *l; - void *v; - register_t *retval; +sys_setrlimit(struct lwp *l, void *v, register_t *retval) { struct sys_setrlimit_args /* { syscallarg(int) which; syscallarg(const struct rlimit *) rlp; } */ *uap = v; - struct proc *p = l->l_proc; - int which = SCARG(uap, which); - struct rlimit alim; - int error; + struct proc *p; + int which; + struct rlimit alim; + int error; + + p = l->l_proc; + which = SCARG(uap, which); error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit)); if (error) @@ -244,16 +300,14 @@ return (dosetrlimit(p, p->p_cred, which, &alim)); } + int -dosetrlimit(p, cred, which, limp) - struct proc *p; - struct pcred *cred; - int which; - struct rlimit *limp; -{ - struct rlimit *alimp; - struct plimit *oldplim; - int error; +dosetrlimit(struct proc *p, struct pcred *cred, int which, + struct rlimit *limp) +{ + struct rlimit *alimp; + struct plimit *oldplim; + int error; if ((u_int)which >= RLIM_NLIMITS) return (EINVAL); @@ -280,6 +334,7 @@ if (p->p_limit->p_refcnt > 1 && (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { + KASSERT(NULL != p->p_inst); p->p_limit = limcopy(oldplim = p->p_limit); limfree(oldplim); alimp = &p->p_rlimit[which]; @@ -361,19 +416,20 @@ return (0); } + /* ARGSUSED */ int -sys_getrlimit(l, v, retval) - struct lwp *l; - void *v; - register_t *retval; +sys_getrlimit(struct lwp *l, void *v, register_t *retval) { struct sys_getrlimit_args /* { syscallarg(int) which; syscallarg(struct rlimit *) rlp; } */ *uap = v; - struct proc *p = l->l_proc; - int which = SCARG(uap, which); + struct proc *p; + int which; + + p = l->l_proc; + which = SCARG(uap, which); if ((u_int)which >= RLIM_NLIMITS) return (EINVAL); @@ -381,23 +437,21 @@ sizeof(struct rlimit))); } + /* * Transform the running time and tick information in proc p into user, * system, and interrupt time usage. */ void -calcru(p, up, sp, ip) - struct proc *p; - struct timeval *up; - struct timeval *sp; - struct timeval *ip; -{ - u_quad_t u, st, ut, it, tot; - unsigned long sec; - long usec; - int s; - struct timeval tv; - struct lwp *l; +calcru(struct proc *p, struct timeval *up, struct timeval *sp, + struct timeval *ip) +{ + u_quad_t u, st, ut, it, tot; + unsigned long sec; + long usec; + int s; + struct timeval tv; + struct lwp *l; s = splstatclock(); st = p->p_sticks; @@ -449,6 +503,7 @@ } } + /* ARGSUSED */ int sys_getrusage(l, v, retval) @@ -496,18 +551,21 @@ *ip++ += *ip2++; } + /* * Make a copy of the plimit structure. * We share these structures copy-on-write after fork, * and copy when a limit is changed. */ struct plimit * -limcopy(lim) - struct plimit *lim; +limcopy(struct plimit *lim) { - struct plimit *newlim; - size_t l = 0; + struct plimit *newlim; + size_t l; + + KASSERT(lim); + l = 0; simple_lock(&lim->p_slock); if (lim->pl_corename != defcorename) l = strlen(lim->pl_corename) + 1; @@ -532,11 +590,13 @@ return (newlim); } + void -limfree(lim) - struct plimit *lim; +limfree(struct plimit *lim) { - int n; + int n; + + KASSERT(lim); simple_lock(&lim->p_slock); n = --lim->p_refcnt; @@ -552,31 +612,31 @@ pool_put(&plimit_pool, lim); } + struct pstats * -pstatscopy(ps) - struct pstats *ps; +pstatscopy(struct pstats *ps) { + struct pstats *newps; - struct pstats *newps; + KASSERT(NULL != ps); newps = pool_get(&pstats_pool, PR_WAITOK); memset(&newps->pstat_startzero, 0, - (unsigned) ((caddr_t)&newps->pstat_endzero - - (caddr_t)&newps->pstat_startzero)); + (unsigned) ((caddr_t)&newps->pstat_endzero - + (caddr_t)&newps->pstat_startzero)); memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy, - ((caddr_t)&newps->pstat_endcopy - - (caddr_t)&newps->pstat_startcopy)); - - return (newps); + ((caddr_t)&newps->pstat_endcopy - + (caddr_t)&newps->pstat_startcopy)); + return(newps); } + void -pstatsfree(ps) - struct pstats *ps; +pstatsfree(struct pstats *ps) { - + KASSERT(NULL != ps); pool_put(&pstats_pool, ps); } @@ -594,9 +654,12 @@ struct proc *ptmp; int i, error = 0; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + if (pid == PROC_CURPROC) ptmp = p; - else if ((ptmp = pfind(pid)) == NULL) + else if ((ptmp = pfind(p->p_inst, pid)) == NULL) error = ESRCH; else { /* @@ -700,6 +763,7 @@ lim = ptmp->p_limit; if (lim->p_refcnt > 1 && (lim->p_lflags & PL_SHAREMOD) == 0) { + KASSERT(NULL != l->l_inst); ptmp->p_limit = limcopy(lim); limfree(lim); lim = ptmp->p_limit; @@ -894,12 +958,13 @@ } static struct uidinfo * -getuidinfo(uid_t uid) +getuidinfo(struct inst *i, uid_t uid) { struct uidinfo *uip; struct uihashhead *uipp; - uipp = UIHASH(uid); + KASSERT(NULL != i); + uipp = UIHASH(i->i_res, uid); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) @@ -915,12 +980,14 @@ } static struct uidinfo * -allocuidinfo(uid_t uid) +allocuidinfo(struct inst *i, uid_t uid) { struct uidinfo *uip; struct uihashhead *uipp; - uipp = UIHASH(uid); + KASSERT(NULL != i); + + uipp = UIHASH(i->i_res, uid); MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); LIST_INSERT_HEAD(uipp, uip, ui_hash); uip->ui_uid = uid; @@ -929,23 +996,23 @@ return uip; } + /* - * Change the count associated with number of processes - * a given user is using. + * Change the count associated with number of processes a given user is using. */ int -chgproccnt(uid_t uid, int diff) +chgproccnt(struct inst *i, uid_t uid, int diff) { struct uidinfo *uip; if (diff == 0) return 0; - if ((uip = getuidinfo(uid)) != NULL) { + if ((uip = getuidinfo(i, uid)) != NULL) { uip->ui_proccnt += diff; KASSERT(uip->ui_proccnt >= 0); if (uip->ui_proccnt > 0) - return uip->ui_proccnt; + return(uip->ui_proccnt); else { if (uip->ui_sbsize == 0) freeuidinfo(uip); @@ -954,9 +1021,9 @@ } else { if (diff < 0) panic("chgproccnt: lost user %lu", (unsigned long)uid); - uip = allocuidinfo(uid); + uip = allocuidinfo(i, uid); uip->ui_proccnt = diff; - return uip->ui_proccnt; + return(uip->ui_proccnt); } } @@ -965,23 +1032,4 @@ { *hiwat = to; return 1; -#ifdef notyet - struct uidinfo *uip; - rlim_t nsb; - int rv = 0; - - if ((uip = getuidinfo(uid)) == NULL) - uip = allocuidinfo(uid); - nsb = uip->ui_sbsize + to - *hiwat; - if (to > *hiwat && nsb > max) - goto done; - *hiwat = to; - uip->ui_sbsize = nsb; - rv = 1; - KASSERT(uip->ui_sbsize >= 0); -done: - if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) - freeuidinfo(uip); - return rv; -#endif } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_sa.c mult-netbsd-3.1/sys/kern/kern_sa.c --- NetBSD-3.1/sys/kern/kern_sa.c 2005-10-28 21:07:02.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_sa.c 2007-11-23 17:59:22.000000000 +0000 @@ -50,9 +50,20 @@ #include #include #include +#include #include + +static POOL_INIT(sadata_pool, sizeof(struct sadata), + 0, 0, 0, "sadatapl", &pool_allocator_nointr); + +static POOL_INIT(sastack_pool, sizeof(struct sastack), + 0, 0, 0, "sastackpl", &pool_allocator_nointr); + +static POOL_INIT(savp_pool, sizeof(struct sadata_vp), + 0, 0, 0, "savppl", &pool_allocator_nointr); + static struct sadata_vp *sa_newsavp(struct sadata *); static __inline int sa_stackused(struct sastack *, struct sadata *); static __inline void sa_setstackfree(struct sastack *, struct sadata *); @@ -74,6 +85,9 @@ size_t, void *, void (*)(void *)); static void sa_upcall_getstate(union sau_state *, struct lwp *); +static POOL_INIT(saupcall_pool, sizeof(struct sadata_upcall), + 0, 0, 0, "plimitpl", &pool_allocator_nointr); + MALLOC_DEFINE(M_SA, "sa", "Scheduler activations"); #define SA_DEBUG @@ -97,6 +111,8 @@ (l)->l_flag |= (f) & L_SA; \ } while (/*CONSTCOND*/ 0) + +/* FIXME - instances? */ SPLAY_PROTOTYPE(sasttree, sastack, sast_node, sast_compare); SPLAY_GENERATE(sasttree, sastack, sast_node, sast_compare); @@ -111,11 +127,11 @@ { struct sadata_upcall *sau; - sau = pool_get(&saupcall_pool, waitok ? PR_WAITOK : PR_NOWAIT); - if (sau) { + sau = pool_get(&saupcall_pool, + waitok ? PR_WAITOK : PR_NOWAIT); + if (sau) sau->sau_arg = NULL; - } - return sau; + return(sau); } /* @@ -126,7 +142,6 @@ void sadata_upcall_free(struct sadata_upcall *sau) { - if (sau == NULL) { return; } @@ -631,8 +646,9 @@ if (vp->savp_lwp != l) { /* * We lost the VP on our way here, this happens for - * instance when we sleep in systrace. This will end - * in an SA_UNBLOCKED_UPCALL in sa_setwoken(). + * instance when we sleep in systrace (which has since + * been removed). This will end in an + * SA_UNBLOCKED_UPCALL in sa_setwoken(). */ DPRINTFN(1,("sa_yield(%d.%d) lost VP\n", p->p_pid, l->l_lid)); @@ -1682,21 +1698,6 @@ #ifdef DEBUG int debug_print_sa(struct proc *); int debug_print_lwp(struct lwp *); -int debug_print_proc(int); - -int -debug_print_proc(int pid) -{ - struct proc *p; - - p = pfind(pid); - if (p == NULL) - printf("No process %d\n", pid); - else - debug_print_sa(p); - - return 0; -} int debug_print_sa(struct proc *p) diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_sig.c mult-netbsd-3.1/sys/kern/kern_sig.c --- NetBSD-3.1/sys/kern/kern_sig.c 2005-11-13 13:55:27.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_sig.c 2007-11-23 10:17:19.000000000 +0000 @@ -74,6 +74,8 @@ #include #include +#include + #include #include /* for coredump */ @@ -86,7 +88,9 @@ static void ksiginfo_exithook(struct proc *, void *); static void ksiginfo_put(struct proc *, const ksiginfo_t *); static ksiginfo_t *ksiginfo_get(struct proc *, int); -static void kpsignal2(struct proc *, const ksiginfo_t *, int); + +static void +kpsignal2(struct proc *p, const ksiginfo_t *, int); sigset_t contsigmask, stopsigmask, sigcantmask; @@ -124,11 +128,11 @@ */ #define CANSIGNAL(p, pc, q, signum) \ ((pc)->pc_ucred->cr_uid == 0 || \ - (pc)->p_ruid == (q)->p_cred->p_ruid || \ - (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ - (pc)->p_ruid == (q)->p_ucred->cr_uid || \ - (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ - ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) + (pc)->p_ruid == (q)->p_cred->p_ruid || \ + (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ + (pc)->p_ruid == (q)->p_ucred->cr_uid || \ + (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ + ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) /* * Remove and return the first ksiginfo element that matches our requested @@ -264,6 +268,7 @@ } } + /* * Make this process not share its sigctx, maintaining all * signal state. @@ -762,6 +767,9 @@ struct pcred *pc; ksiginfo_t ksi; + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_proc->p_inst); + cp = l->l_proc; pc = cp->p_cred; if ((u_int)SCARG(uap, signum) >= NSIG) @@ -773,7 +781,7 @@ ksi.ksi_uid = cp->p_ucred->cr_uid; if (SCARG(uap, pid) > 0) { /* kill single process */ - if ((p = pfind(SCARG(uap, pid))) == NULL) + if ((p = pfind(cp->p_inst, SCARG(uap, pid))) == NULL) return (ESRCH); if (!CANSIGNAL(cp, pc, p, SCARG(uap, signum))) return (EPERM); @@ -792,27 +800,28 @@ /* NOTREACHED */ } -/* - * Common code for kill process group/broadcast kill. - * cp is calling process. - */ + int killpg1(struct proc *cp, ksiginfo_t *ksi, int pgid, int all) { struct proc *p; struct pcred *pc; struct pgrp *pgrp; - int nfound; - int signum = ksi->ksi_signo; + int nfound, signum; + struct inst *i; + signum = ksi->ksi_signo; pc = cp->p_cred; + i = cp->p_inst; + KASSERT(NULL != i); nfound = 0; + if (all) { /* * broadcast */ - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + proclist_lock_read(i); + PROCLIST_FOREACH(p, &i->i_allproc) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp || !CANSIGNAL(cp, pc, p, signum)) continue; @@ -820,7 +829,7 @@ if (signum) kpsignal2(p, ksi, 1); } - proclist_unlock_read(); + proclist_unlock_read(i); } else { if (pgid == 0) /* @@ -828,7 +837,7 @@ */ pgrp = cp->p_pgrp; else { - pgrp = pgfind(pgid); + pgrp = pgfind(i, pgid); if (pgrp == NULL) return (ESRCH); } @@ -844,31 +853,31 @@ return (nfound ? 0 : ESRCH); } -/* - * Send a signal to a process group. - */ + void -gsignal(int pgid, int signum) +gsignal(struct inst *i, int pgid, int signum) { - ksiginfo_t ksi; + ksiginfo_t ksi; + + KASSERT(NULL != i); + KSI_INIT_EMPTY(&ksi); ksi.ksi_signo = signum; - kgsignal(pgid, &ksi, NULL); + kgsignal(i, pgid, &ksi, NULL); } void -kgsignal(int pgid, ksiginfo_t *ksi, void *data) +kgsignal(struct inst *i, int pgid, ksiginfo_t *ksi, void *data) { - struct pgrp *pgrp; + struct pgrp *pgrp; + + KASSERT(NULL != i); - if (pgid && (pgrp = pgfind(pgid))) + if (pgid && (pgrp = pgfind(i, pgid))) kpgsignal(pgrp, ksi, data, 0); } -/* - * Send a signal to a process group. If checktty is 1, - * limit to members which have a controlling terminal. - */ + void pgsignal(struct pgrp *pgrp, int sig, int checkctty) { @@ -878,17 +887,20 @@ kpgsignal(pgrp, &ksi, NULL, checkctty); } + void kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty) { - struct proc *p; + struct proc *p; - if (pgrp) - LIST_FOREACH(p, &pgrp->pg_members, p_pglist) - if (checkctty == 0 || p->p_flag & P_CONTROLT) - kpsignal(p, ksi, data); + if ( ! pgrp) + return; + LIST_FOREACH(p, &pgrp->pg_members, p_pglist) + if (checkctty == 0 || p->p_flag & P_CONTROLT) + kpsignal(p, ksi, data); } + /* * Send a signal caused by a trap to the current process. * If it will be caught immediately, deliver it with correct code. @@ -950,7 +962,8 @@ ksi.ksi_status = p->p_xstat; ksi.ksi_utime = p->p_stats->p_ru.ru_utime.tv_sec; ksi.ksi_stime = p->p_stats->p_ru.ru_stime.tv_sec; - kpsignal2(p->p_pptr, &ksi, dolock); + if (p->p_pptr) + kpsignal2(p->p_pptr, &ksi, dolock); } /* @@ -981,7 +994,6 @@ void kpsignal1(struct proc *p, ksiginfo_t *ksi, void *data, int dolock) { - if ((p->p_flag & P_WEXIT) == 0 && data) { size_t fd; struct filedesc *fdp = p->p_fd; @@ -999,14 +1011,22 @@ kpsignal2(p, ksi, dolock); } + static void kpsignal2(struct proc *p, const ksiginfo_t *ksi, int dolock) { - struct lwp *l, *suspended = NULL; + struct lwp *l, *suspended; struct sadata_vp *vp; - int s = 0, prop, allsusp; - sig_t action; - int signum = ksi->ksi_signo; + int s, prop, allsusp; + sig_t action; + int signum; + + signum = ksi->ksi_signo; + suspended = NULL; + s = 0; + + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); #ifdef DIAGNOSTIC if (signum <= 0 || signum >= NSIG) @@ -1228,7 +1248,8 @@ } sigdelset(&p->p_sigctx.ps_siglist, signum); p->p_xstat = signum; - if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0) { + if (p->p_pptr && + ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)) { /* * XXXSMP: recursive call; don't lock * the second time around. @@ -1580,7 +1601,7 @@ prop & SA_TTYSTOP)) break; /* == ignore */ p->p_xstat = signum; - if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0) + if (p->p_pptr && ((p->p_pptr->p_flag & P_NOCLDSTOP)) == 0) child_psignal(p, dolock); if (dolock) SCHED_LOCK(s); @@ -1644,7 +1665,6 @@ proc_stop(struct proc *p, int wakeup) { struct lwp *l; - struct proc *parent; struct sadata_vp *vp; SCHED_ASSERT_LOCKED(); @@ -1652,8 +1672,8 @@ /* XXX lock process LWP state */ p->p_flag &= ~P_WAITED; p->p_stat = SSTOP; - parent = p->p_pptr; - parent->p_nstopchild++; + if (p->p_pptr) + p->p_pptr->p_nstopchild++; if (p->p_flag & P_SA) { /* @@ -1735,7 +1755,7 @@ out: /* XXX unlock process LWP state */ - if (wakeup) + if (wakeup && p->p_pptr) sched_wakeup((caddr_t)p->p_pptr); } @@ -1763,7 +1783,7 @@ * interruptable LWPs if this is the case. */ - if (!(p->p_flag & P_WAITED)) + if (p->p_pptr && !(p->p_flag & P_WAITED)) p->p_pptr->p_nstopchild--; p->p_stat = SACTIVE; LIST_FOREACH(l, &p->p_lwps, l_sibling) { diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_subr.c mult-netbsd-3.1/sys/kern/kern_subr.c --- NetBSD-3.1/sys/kern/kern_subr.c 2005-12-29 20:00:12.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_subr.c 2007-11-10 19:27:11.000000000 +0000 @@ -92,7 +92,6 @@ #include "opt_md.h" #include "opt_syscall_debug.h" #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -104,7 +103,6 @@ #include #include #include -#include #include #include @@ -1344,7 +1342,7 @@ trace_enter(struct lwp *l, register_t code, register_t realcode, const struct sysent *callp, void *args) { -#if defined(KTRACE) || defined(SYSTRACE) +#if defined(KTRACE) struct proc *p = l->l_proc; #endif @@ -1357,10 +1355,6 @@ ktrsyscall(p, code, realcode, callp, args); #endif /* KTRACE */ -#ifdef SYSTRACE - if (ISSET(p->p_flag, P_SYSTRACE)) - return systrace_enter(p, code, args); -#endif return 0; } @@ -1375,7 +1369,7 @@ trace_exit(struct lwp *l, register_t code, void *args, register_t rval[], int error) { -#if defined(KTRACE) || defined(SYSTRACE) +#if defined(KTRACE) struct proc *p = l->l_proc; #endif @@ -1390,12 +1384,4 @@ KERNEL_PROC_UNLOCK(l); } #endif /* KTRACE */ - -#ifdef SYSTRACE - if (ISSET(p->p_flag, P_SYSTRACE)) { - KERNEL_PROC_LOCK(l); - systrace_exit(p, code, args, rval, error); - KERNEL_PROC_UNLOCK(l); - } -#endif } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_synch.c mult-netbsd-3.1/sys/kern/kern_synch.c --- NetBSD-3.1/sys/kern/kern_synch.c 2005-10-21 18:39:40.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_synch.c 2007-11-23 10:17:19.000000000 +0000 @@ -100,6 +100,8 @@ #include #include +#include + #include #ifdef KTRACE @@ -242,6 +244,7 @@ */ #define CCPU_SHIFT 11 + /* * Recompute process priorities, every hz ticks. */ @@ -249,74 +252,95 @@ void schedcpu(void *arg) { - fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); - struct lwp *l; - struct proc *p; - int s, minslp; - unsigned int newcpu; - int clkhz; + fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); + struct lwp *l; + struct proc *p; + struct inst *i; + int s, minslp, clkhz; + unsigned int newcpu; + + instlist_lock_read(); + + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + PROCLIST_FOREACH(p, &i->i_allproc) { + /* + * Increment time in/out of memory and sleep + * time (if sleeping). We ignore overflow; with + * 16-bit int's (remember them?) overflow takes + * 45 days. + */ + minslp = 2; + LIST_FOREACH(l, &p->p_lwps, l_sibling) { + l->l_swtime++; + if (l->l_stat == LSSLEEP || + l->l_stat == LSSTOP || + l->l_stat == LSSUSPENDED) { + l->l_slptime++; + minslp = min(minslp, l->l_slptime); + } else + minslp = 0; + } + p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; + + /* + * If the process has slept the entire second, + * stop recalculating its priority until it + * wakes up. + */ + if (minslp > 1) + continue; + + /* Prevent state changes */ + s = splstatclock(); + + /* + * p_pctcpu is only for ps. + */ + clkhz = stathz != 0 ? stathz : hz; - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { - /* - * Increment time in/out of memory and sleep time - * (if sleeping). We ignore overflow; with 16-bit int's - * (remember them?) overflow takes 45 days. - */ - minslp = 2; - LIST_FOREACH(l, &p->p_lwps, l_sibling) { - l->l_swtime++; - if (l->l_stat == LSSLEEP || l->l_stat == LSSTOP || - l->l_stat == LSSUSPENDED) { - l->l_slptime++; - minslp = min(minslp, l->l_slptime); - } else - minslp = 0; - } - p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; - /* - * If the process has slept the entire second, - * stop recalculating its priority until it wakes up. - */ - if (minslp > 1) - continue; - s = splstatclock(); /* prevent state changes */ - /* - * p_pctcpu is only for ps. - */ - clkhz = stathz != 0 ? stathz : hz; #if (FSHIFT >= CCPU_SHIFT) - p->p_pctcpu += (clkhz == 100)? - ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT): - 100 * (((fixpt_t) p->p_cpticks) + p->p_pctcpu += (clkhz == 100) ? + ((fixpt_t) p->p_cpticks) << + (FSHIFT - CCPU_SHIFT) : + 100 * (((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT)) / clkhz; #else - p->p_pctcpu += ((FSCALE - ccpu) * - (p->p_cpticks * FSCALE / clkhz)) >> FSHIFT; + p->p_pctcpu += ((FSCALE - ccpu) * + (p->p_cpticks * FSCALE / clkhz)) >> FSHIFT; #endif - p->p_cpticks = 0; - newcpu = (u_int)decay_cpu(loadfac, p->p_estcpu); - p->p_estcpu = newcpu; - splx(s); /* Done with the process CPU ticks update */ - SCHED_LOCK(s); - LIST_FOREACH(l, &p->p_lwps, l_sibling) { - if (l->l_slptime > 1) - continue; - resetpriority(l); - if (l->l_priority >= PUSER) { - if (l->l_stat == LSRUN && - (l->l_flag & L_INMEM) && - (l->l_priority / PPQ) != (l->l_usrpri / PPQ)) { - remrunqueue(l); - l->l_priority = l->l_usrpri; - setrunqueue(l); - } else - l->l_priority = l->l_usrpri; + + p->p_cpticks = 0; + newcpu = (u_int)decay_cpu + (loadfac, p->p_estcpu); + p->p_estcpu = newcpu; + + /* Done with the process CPU ticks update */ + splx(s); + SCHED_LOCK(s); + LIST_FOREACH(l, &p->p_lwps, l_sibling) { + if (l->l_slptime > 1) + continue; + resetpriority(l); + if (l->l_priority >= PUSER) { + if (l->l_stat == LSRUN && + (l->l_flag & L_INMEM) && + (l->l_priority / PPQ) != + (l->l_usrpri / PPQ)) { + remrunqueue(l); + l->l_priority = l->l_usrpri; + setrunqueue(l); + } else + l->l_priority = l->l_usrpri; + } } + SCHED_UNLOCK(s); } - SCHED_UNLOCK(s); + proclist_unlock_read(i); } - proclist_unlock_read(); + + instlist_unlock_read(); + uvm_meter(); wakeup((caddr_t)&lbolt); callout_schedule(&schedcpu_ch, hz); @@ -1155,42 +1179,49 @@ void suspendsched() { - struct lwp *l; - int s; + struct lwp *l; + struct inst *i; + int s; /* * Convert all non-P_SYSTEM LSSLEEP or LSRUN processes to * LSSUSPENDED. */ - proclist_lock_read(); + instlist_lock_read(); SCHED_LOCK(s); - LIST_FOREACH(l, &alllwp, l_list) { - if ((l->l_proc->p_flag & P_SYSTEM) != 0) - continue; - - switch (l->l_stat) { - case LSRUN: - l->l_proc->p_nrlwps--; - if ((l->l_flag & L_INMEM) != 0) - remrunqueue(l); - /* FALLTHROUGH */ - case LSSLEEP: - l->l_stat = LSSUSPENDED; - break; - case LSONPROC: - /* - * XXX SMP: we need to deal with processes on - * others CPU ! - */ - break; - default: - break; + + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + if ((l->l_proc->p_flag & P_SYSTEM) != 0) + continue; + + switch (l->l_stat) { + case LSRUN: + l->l_proc->p_nrlwps--; + if ((l->l_flag & L_INMEM) != 0) + remrunqueue(l); + /* FALLTHROUGH */ + case LSSLEEP: + l->l_stat = LSSUSPENDED; + break; + case LSONPROC: + /* + * XXX SMP: we need to deal with + * processes on others CPU ! + */ + break; + default: + break; + } } + proclist_unlock_read(i); } SCHED_UNLOCK(s); - proclist_unlock_read(); + instlist_unlock_read(); } + /* * Low-level routines to access the run queue. Optimised assembler * routines can override these. diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_sysctl.c mult-netbsd-3.1/sys/kern/kern_sysctl.c --- NetBSD-3.1/sys/kern/kern_sysctl.c 2006-03-24 22:44:29.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_sysctl.c 2007-11-26 15:42:56.000000000 +0000 @@ -152,17 +152,9 @@ caddr_t sysctl_memaddr; size_t sysctl_memsize; -/* - * Attributes stored in the kernel. - */ -char hostname[MAXHOSTNAMELEN]; -int hostnamelen; - -char domainname[MAXHOSTNAMELEN]; -int domainnamelen; - long hostid; +/* FIXME - instances (maybe not...) */ #ifdef INSECURE int securelevel = -1; #else diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_systrace.c mult-netbsd-3.1/sys/kern/kern_systrace.c --- NetBSD-3.1/sys/kern/kern_systrace.c 2006-10-16 21:36:50.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_systrace.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1733 +0,0 @@ -/* $NetBSD: kern_systrace.c,v 1.44.2.4 2006/10/16 20:36:50 ghen Exp $ */ - -/* - * Copyright 2002, 2003 Niels Provos - * 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 Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.44.2.4 2006/10/16 20:36:50 ghen Exp $"); - -#include "opt_systrace.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __NetBSD__ -#define SYSTRACE_LOCK(fst, p) lockmgr(&fst->lock, LK_EXCLUSIVE, NULL) -#define SYSTRACE_UNLOCK(fst, p) lockmgr(&fst->lock, LK_RELEASE, NULL) -#else -#define SYSTRACE_LOCK(fst, p) lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p) -#define SYSTRACE_UNLOCK(fst, p) lockmgr(&fst->lock, LK_RELEASE, NULL, p) -#endif -#ifndef M_XDATA -MALLOC_DEFINE(M_SYSTR, "systrace", "systrace"); -#define M_XDATA M_SYSTR -#endif - -#ifdef __NetBSD__ -dev_type_open(systraceopen); -#else -cdev_decl(systrace); -#endif - -#ifdef __NetBSD__ -int systracef_read(struct file *, off_t *, struct uio *, struct ucred *, - int); -int systracef_write(struct file *, off_t *, struct uio *, struct ucred *, - int); -int systracef_poll(struct file *, int, struct proc *); -#else -int systracef_read(struct file *, off_t *, struct uio *, struct ucred *); -int systracef_write(struct file *, off_t *, struct uio *, struct ucred *); -int systracef_select(struct file *, int, struct proc *); -#endif -int systracef_ioctl(struct file *, u_long, void *, struct proc *); -int systracef_close(struct file *, struct proc *); - -struct str_policy { - TAILQ_ENTRY(str_policy) next; - - int nr; - - const struct emul *emul; /* Is only valid for this emulation */ - - int refcount; - - int nsysent; - u_char *sysent; -}; - -#define STR_PROC_ONQUEUE 0x01 -#define STR_PROC_WAITANSWER 0x02 -#define STR_PROC_SYSCALLRES 0x04 -#define STR_PROC_REPORT 0x08 /* Report emulation */ -#define STR_PROC_NEEDSEQNR 0x10 /* Answer must quote seqnr */ -#define STR_PROC_SETEUID 0x20 /* Elevate privileges */ -#define STR_PROC_SETEGID 0x40 -#define STR_PROC_DIDSETUGID 0x80 - -struct str_process { - TAILQ_ENTRY(str_process) next; - - struct proc *proc; - const struct emul *oldemul; - uid_t olduid; - gid_t oldgid; - - pid_t pid; - - struct fsystrace *parent; - struct str_policy *policy; - - struct systrace_replace *replace; - char *fname[SYSTR_MAXFNAME]; - size_t nfname; - - int flags; - short answer; - short error; - u_int16_t seqnr; /* expected reply sequence number */ - - uid_t seteuid; - uid_t saveuid; - gid_t setegid; - gid_t savegid; -}; - -uid_t systrace_seteuid(struct proc *, uid_t); -gid_t systrace_setegid(struct proc *, gid_t); -void systrace_lock(void); -void systrace_unlock(void); - -/* Needs to be called with fst locked */ - -int systrace_attach(struct fsystrace *, pid_t); -int systrace_detach(struct str_process *); -int systrace_answer(struct str_process *, struct systrace_answer *); -int systrace_io(struct str_process *, struct systrace_io *); -int systrace_policy(struct fsystrace *, struct systrace_policy *); -int systrace_preprepl(struct str_process *, struct systrace_replace *); -int systrace_replace(struct str_process *, size_t, register_t []); -int systrace_getcwd(struct fsystrace *, struct str_process *); -int systrace_fname(struct str_process *, caddr_t, size_t); -void systrace_replacefree(struct str_process *); - -int systrace_processready(struct str_process *); -struct proc *systrace_find(struct str_process *); -struct str_process *systrace_findpid(struct fsystrace *fst, pid_t pid); -void systrace_wakeup(struct fsystrace *); -void systrace_closepolicy(struct fsystrace *, struct str_policy *); -int systrace_insert_process(struct fsystrace *, struct proc *, - struct str_process **); -struct str_policy *systrace_newpolicy(struct fsystrace *, int); -int systrace_msg_child(struct fsystrace *, struct str_process *, pid_t); -int systrace_msg_policyfree(struct fsystrace *, struct str_policy *); -int systrace_msg_ask(struct fsystrace *, struct str_process *, - int, size_t, register_t []); -int systrace_msg_result(struct fsystrace *, struct str_process *, - int, int, size_t, register_t [], register_t []); -int systrace_msg_emul(struct fsystrace *, struct str_process *); -int systrace_msg_ugid(struct fsystrace *, struct str_process *); -int systrace_make_msg(struct str_process *, int, struct str_message *); - -static const struct fileops systracefops = { - systracef_read, - systracef_write, - systracef_ioctl, - fnullop_fcntl, - systracef_poll, - fbadop_stat, - systracef_close, - fnullop_kqfilter -}; - -#ifdef __NetBSD__ -POOL_INIT(systr_proc_pl, sizeof(struct str_process), 0, 0, 0, "strprocpl", - NULL); -POOL_INIT(systr_policy_pl, sizeof(struct str_policy), 0, 0, 0, "strpolpl", - NULL); -POOL_INIT(systr_msgcontainer_pl, sizeof(struct str_msgcontainer), 0, 0, 0, - "strmsgpl", NULL); -#else -struct pool systr_proc_pl; -struct pool systr_policy_pl; -struct pool systr_msgcontainer_pl; -#endif - -int systrace_debug = 0; -struct lock systrace_lck; - -#ifdef __NetBSD__ -const struct cdevsw systrace_cdevsw = { - systraceopen, noclose, noread, nowrite, noioctl, - nostop, notty, nopoll, nommap, nokqfilter, -}; -#endif - -#define DPRINTF(y) if (systrace_debug) printf y; - -/* ARGSUSED */ -int -systracef_read(struct file *fp, off_t *poff, struct uio *uio, - struct ucred *cred -#ifdef __NetBSD__ - , int flags -#endif -) -{ - struct fsystrace *fst = (struct fsystrace *)fp->f_data; - struct str_msgcontainer *cont; - int error = 0; - - if (uio->uio_resid != sizeof(struct str_message)) - return (EINVAL); - - again: - systrace_lock(); - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - if ((cont = TAILQ_FIRST(&fst->messages)) != NULL) { - error = uiomove((caddr_t)&cont->msg, - sizeof(struct str_message), uio); - if (!error) { - TAILQ_REMOVE(&fst->messages, cont, next); - if (!SYSTR_MSG_NOPROCESS(cont)) - CLR(cont->strp->flags, STR_PROC_ONQUEUE); - pool_put(&systr_msgcontainer_pl, cont); - - } - } else if (TAILQ_FIRST(&fst->processes) == NULL) { - /* EOF situation */ - ; - } else { - if (fp->f_flag & FNONBLOCK) - error = EAGAIN; - else { - SYSTRACE_UNLOCK(fst, curlwp); - error = tsleep(fst, PWAIT|PCATCH, "systrrd", 0); - if (error) - goto out; - goto again; - } - - } - - SYSTRACE_UNLOCK(fst, curlwp); - out: - return (error); -} - -/* ARGSUSED */ -int -systracef_write(struct file *fp, off_t *poff, struct uio *uio, - struct ucred *cred -#ifdef __NetBSD__ - , int flags -#endif -) -{ - return (EIO); -} - -#define POLICY_VALID(x) ((x) == SYSTR_POLICY_PERMIT || \ - (x) == SYSTR_POLICY_ASK || \ - (x) == SYSTR_POLICY_NEVER) - -/* ARGSUSED */ -int -systracef_ioctl(struct file *fp, u_long cmd, void *data, struct proc *p) -{ - int ret = 0; - struct fsystrace *fst = (struct fsystrace *)fp->f_data; -#ifdef __NetBSD__ - struct cwdinfo *cwdp; -#else - struct filedesc *fdp; -#endif - struct str_process *strp = NULL; - pid_t pid = 0; - - switch (cmd) { - case FIONBIO: - case FIOASYNC: - return (0); - - case STRIOCDETACH: - case STRIOCREPORT: - pid = *(pid_t *)data; - if (!pid) - ret = EINVAL; - break; - case STRIOCANSWER: - pid = ((struct systrace_answer *)data)->stra_pid; - if (!pid) - ret = EINVAL; - break; - case STRIOCIO: - pid = ((struct systrace_io *)data)->strio_pid; - if (!pid) - ret = EINVAL; - break; - case STRIOCGETCWD: - pid = *(pid_t *)data; - if (!pid) - ret = EINVAL; - break; - case STRIOCATTACH: - case STRIOCRESCWD: - case STRIOCPOLICY: - break; - case STRIOCREPLACE: - pid = ((struct systrace_replace *)data)->strr_pid; - if (!pid) - ret = EINVAL; - break; - default: - ret = EINVAL; - break; - } - - if (ret) - return (ret); - - systrace_lock(); - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - if (pid) { - strp = systrace_findpid(fst, pid); - if (strp == NULL) { - ret = ESRCH; - goto unlock; - } - } - - switch (cmd) { - case STRIOCATTACH: - pid = *(pid_t *)data; - if (!pid) - ret = EINVAL; - else - ret = systrace_attach(fst, pid); - DPRINTF(("%s: attach to %u: %d\n", __func__, pid, ret)); - break; - case STRIOCDETACH: - ret = systrace_detach(strp); - break; - case STRIOCREPORT: - SET(strp->flags, STR_PROC_REPORT); - break; - case STRIOCANSWER: - ret = systrace_answer(strp, (struct systrace_answer *)data); - break; - case STRIOCIO: - ret = systrace_io(strp, (struct systrace_io *)data); - break; - case STRIOCPOLICY: - ret = systrace_policy(fst, (struct systrace_policy *)data); - break; - case STRIOCREPLACE: - ret = systrace_preprepl(strp, (struct systrace_replace *)data); - break; - case STRIOCRESCWD: - if (!fst->fd_pid) { - ret = EINVAL; - break; - } -#ifdef __NetBSD__ - cwdp = p->p_cwdi; - - /* Release cwd from other process */ - if (cwdp->cwdi_cdir) - vrele(cwdp->cwdi_cdir); - if (cwdp->cwdi_rdir) - vrele(cwdp->cwdi_rdir); - cwdp->cwdi_cdir = fst->fd_cdir; - cwdp->cwdi_rdir = fst->fd_rdir; -#else - fdp = p->p_fd; - - /* Release cwd from other process */ - if (fdp->fd_cdir) - vrele(fdp->fd_cdir); - if (fdp->fd_rdir) - vrele(fdp->fd_rdir); - /* This restores the cwd we had before */ - fdp->fd_cdir = fst->fd_cdir; - fdp->fd_rdir = fst->fd_rdir; -#endif - /* Note that we are normal again */ - fst->fd_pid = 0; - fst->fd_cdir = fst->fd_rdir = NULL; - break; - case STRIOCGETCWD: - ret = systrace_getcwd(fst, strp); - break; - default: - ret = EINVAL; - break; - } - - unlock: - SYSTRACE_UNLOCK(fst, curlwp); - - return (ret); -} - -#ifdef __NetBSD__ -int -systracef_poll(struct file *fp, int events, struct proc *p) -{ - struct fsystrace *fst = (struct fsystrace *)fp->f_data; - int revents = 0; - - if ((events & (POLLIN | POLLRDNORM)) == 0) - return (revents); - - systrace_lock(); - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - if (!TAILQ_EMPTY(&fst->messages)) - revents |= events & (POLLIN | POLLRDNORM); - if (revents == 0) - selrecord(p, &fst->si); - SYSTRACE_UNLOCK(fst, p); - - return (revents); -} -#else -int -systracef_select(struct file *fp, int which, struct proc *p) -{ - struct fsystrace *fst = (struct fsystrace *)fp->f_data; - int ready = 0; - - if (which != FREAD) - return (0); - - systrace_lock(); - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - ready = TAILQ_FIRST(&fst->messages) != NULL; - if (!ready) - selrecord(p, &fst->si); - SYSTRACE_UNLOCK(fst, p); - - return (ready); -} -#endif /* __NetBSD__ */ - -/* ARGSUSED */ -int -systracef_close(struct file *fp, struct proc *p) -{ - struct fsystrace *fst = (struct fsystrace *)fp->f_data; - struct str_process *strp; - struct str_msgcontainer *cont; - struct str_policy *strpol; - - systrace_lock(); - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - - /* Untrace all processes */ - for (strp = TAILQ_FIRST(&fst->processes); strp; - strp = TAILQ_FIRST(&fst->processes)) { - struct proc *q = strp->proc; - - systrace_detach(strp); - psignal(q, SIGKILL); - } - - /* Clean up fork and exit messages */ - for (cont = TAILQ_FIRST(&fst->messages); cont; - cont = TAILQ_FIRST(&fst->messages)) { - TAILQ_REMOVE(&fst->messages, cont, next); - pool_put(&systr_msgcontainer_pl, cont); - } - - /* Clean up all policies */ - for (strpol = TAILQ_FIRST(&fst->policies); strpol; - strpol = TAILQ_FIRST(&fst->policies)) - systrace_closepolicy(fst, strpol); - - /* Release vnodes */ - if (fst->fd_cdir) - vrele(fst->fd_cdir); - if (fst->fd_rdir) - vrele(fst->fd_rdir); - SYSTRACE_UNLOCK(fst, curlwp); - - FREE(fp->f_data, M_XDATA); - fp->f_data = NULL; - - return (0); -} - -void -systrace_lock(void) -{ -#ifdef __NetBSD__ - lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL); -#else - lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL, curlwp); -#endif -} - -void -systrace_unlock(void) -{ -#ifdef __NetBSD__ - lockmgr(&systrace_lck, LK_RELEASE, NULL); -#else - lockmgr(&systrace_lck, LK_RELEASE, NULL, curlwp); -#endif -} - -void -systrace_init(void) -{ - -#ifndef __NetBSD__ - pool_init(&systr_proc_pl, sizeof(struct str_process), 0, 0, 0, - "strprocpl", NULL); - pool_init(&systr_policy_pl, sizeof(struct str_policy), 0, 0, 0, - "strpolpl", NULL); - pool_init(&systr_msgcontainer_pl, sizeof(struct str_msgcontainer), - 0, 0, 0, "strmsgpl", NULL); -#endif - lockinit(&systrace_lck, PLOCK, "systrace", 0, 0); -} - -int -systraceopen(dev_t dev, int flag, int mode, struct proc *p) -{ - struct fsystrace *fst; - struct file *fp; - int error, fd; - - /* falloc() will use the descriptor for us. */ - if ((error = falloc(p, &fp, &fd)) != 0) - return (error); - - MALLOC(fst, struct fsystrace *, sizeof(*fst), M_XDATA, M_WAITOK); - - memset(fst, 0, sizeof(struct fsystrace)); - lockinit(&fst->lock, PLOCK, "systrace", 0, 0); - - TAILQ_INIT(&fst->processes); - TAILQ_INIT(&fst->messages); - TAILQ_INIT(&fst->policies); - - if (suser(p->p_ucred, &p->p_acflag) == 0) - fst->issuser = 1; - fst->p_ruid = p->p_cred->p_ruid; - fst->p_rgid = p->p_cred->p_rgid; - - return fdclone(p, fp, fd, flag, &systracefops, fst); -} - -void -systrace_wakeup(struct fsystrace *fst) -{ - wakeup((caddr_t)fst); - selwakeup(&fst->si); -} - -struct proc * -systrace_find(struct str_process *strp) -{ - struct proc *proc; - - if ((proc = pfind(strp->pid)) == NULL) - return (NULL); - - if (proc != strp->proc) - return (NULL); - - if (!ISSET(proc->p_flag, P_SYSTRACE)) - return (NULL); - - return (proc); -} - -void -systrace_sys_exit(struct proc *proc) -{ - struct str_process *strp; - struct fsystrace *fst; - - systrace_lock(); - strp = proc->p_systrace; - if (strp != NULL) { - fst = strp->parent; - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - - /* Insert Exit message */ - systrace_msg_child(fst, strp, -1); - - systrace_detach(strp); - SYSTRACE_UNLOCK(fst, curlwp); - } else - systrace_unlock(); - CLR(proc->p_flag, P_SYSTRACE); -} - -void -systrace_sys_fork(struct proc *oldproc, struct proc *p) -{ - struct str_process *oldstrp, *strp; - struct fsystrace *fst; - - systrace_lock(); - oldstrp = oldproc->p_systrace; - if (oldstrp == NULL) { - systrace_unlock(); - return; - } - - fst = oldstrp->parent; - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - - if (systrace_insert_process(fst, p, &strp)) { - /* We need to kill the child */ - psignal(p, SIGKILL); - goto out; - } - - /* Reference policy */ - if ((strp->policy = oldstrp->policy) != NULL) - strp->policy->refcount++; - - /* Insert fork message */ - systrace_msg_child(fst, oldstrp, p->p_pid); - out: - SYSTRACE_UNLOCK(fst, curlwp); -} - -int -systrace_enter(struct proc *p, register_t code, void *v) -{ - const struct sysent *callp; - struct str_process *strp; - struct str_policy *strpolicy; - struct fsystrace *fst; - struct pcred *pc; - int policy, error = 0, maycontrol = 0, issuser = 0; - size_t argsize; - - systrace_lock(); - strp = p->p_systrace; - if (strp == NULL) { - systrace_unlock(); - return (EINVAL); - } - - KASSERT(strp->proc == p); - - fst = strp->parent; - - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - - /* - * We can not monitor a SUID process unless we are root, - * but we wait until it executes something unprivileged. - * A non-root user may only monitor if the real uid and - * real gid match the monitored process. Changing the - * uid or gid causes P_SUGID to be set. - */ - if (fst->issuser) { - maycontrol = 1; - issuser = 1; - } else if (!(p->p_flag & P_SUGID)) { - maycontrol = fst->p_ruid == p->p_cred->p_ruid && - fst->p_rgid == p->p_cred->p_rgid; - } - - if (!maycontrol) { - policy = SYSTR_POLICY_PERMIT; - } else { - /* Find out current policy */ - if ((strpolicy = strp->policy) == NULL) - policy = SYSTR_POLICY_ASK; - else { - if (code >= strpolicy->nsysent) - policy = SYSTR_POLICY_NEVER; - else - policy = strpolicy->sysent[code]; - } - } - - callp = p->p_emul->e_sysent + code; - - /* Fast-path */ - if (policy != SYSTR_POLICY_ASK) { - if (policy != SYSTR_POLICY_PERMIT) { - if (policy > 0) - error = policy; - else - error = EPERM; - } - strp->oldemul = NULL; - systrace_replacefree(strp); - SYSTRACE_UNLOCK(fst, p); - return (error); - } - - /* Get the (adjusted) argsize */ - argsize = callp->sy_argsize; -#ifdef _LP64 - if (p->p_flag & P_32) - argsize = argsize << 1; -#endif - - /* Puts the current process to sleep, return unlocked */ - error = systrace_msg_ask(fst, strp, code, argsize, v); - - /* lock has been released in systrace_msg_ask() */ - fst = NULL; - /* We might have detached by now for some reason */ - if (!error && (strp = p->p_systrace) != NULL) { - /* XXX - do I need to lock here? */ - if (strp->answer == SYSTR_POLICY_NEVER) { - error = strp->error; - systrace_replacefree(strp); - } else { - if (ISSET(strp->flags, STR_PROC_SYSCALLRES)) { -#ifndef __NetBSD__ - CLR(strp->flags, STR_PROC_SYSCALLRES); -#endif - } - /* Replace the arguments if necessary */ - if (strp->replace != NULL) { - error = systrace_replace(strp, argsize, v); - } - } - } - - systrace_lock(); - if ((strp = p->p_systrace) == NULL) - goto out; - - if (error) { - strp->oldemul = NULL; - goto out; - } - - pc = p->p_cred; - strp->oldemul = p->p_emul; - strp->olduid = pc->p_ruid; - strp->oldgid = pc->p_rgid; - - /* Elevate privileges as desired */ - if (issuser) { - if (ISSET(strp->flags, STR_PROC_SETEUID)) { - strp->saveuid = systrace_seteuid(p, strp->seteuid); - SET(strp->flags, STR_PROC_DIDSETUGID); - } - if (ISSET(strp->flags, STR_PROC_SETEGID)) { - strp->savegid = systrace_setegid(p, strp->setegid); - SET(strp->flags, STR_PROC_DIDSETUGID); - } - } else - CLR(strp->flags, - STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID); - - out: - systrace_unlock(); - return (error); -} - -void -systrace_exit(struct proc *p, register_t code, void *v, register_t retval[], - int error) -{ - const struct sysent *callp; - struct str_process *strp; - struct fsystrace *fst; - struct pcred *pc; - - /* Report change in emulation */ - systrace_lock(); - strp = p->p_systrace; - if (strp == NULL || strp->oldemul == NULL) { - systrace_unlock(); - return; - } - DPRINTF(("exit syscall %lu, oldemul %p\n", (u_long)code, strp->oldemul)); - - /* Return to old privileges */ - pc = p->p_cred; - if (ISSET(strp->flags, STR_PROC_DIDSETUGID)) { - if (ISSET(strp->flags, STR_PROC_SETEUID)) { - if (pc->pc_ucred->cr_uid == strp->seteuid) - systrace_seteuid(p, strp->saveuid); - } - if (ISSET(strp->flags, STR_PROC_SETEGID)) { - if (pc->pc_ucred->cr_gid == strp->setegid) - systrace_setegid(p, strp->savegid); - } - } - CLR(strp->flags, - STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID); - - systrace_replacefree(strp); - - if (p->p_flag & P_SUGID) { - if ((fst = strp->parent) == NULL || !fst->issuser) { - systrace_unlock(); - return; - } - } - - /* See if we should force a report */ - if (ISSET(strp->flags, STR_PROC_REPORT)) { - CLR(strp->flags, STR_PROC_REPORT); - strp->oldemul = NULL; - } - - if (p->p_emul != strp->oldemul && strp != NULL) { - fst = strp->parent; - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - - /* Old policy is without meaning now */ - if (strp->policy) { - systrace_closepolicy(fst, strp->policy); - strp->policy = NULL; - } - systrace_msg_emul(fst, strp); - } else - systrace_unlock(); - - /* Report if effective uid or gid changed */ - systrace_lock(); - strp = p->p_systrace; - if (strp != NULL && (strp->olduid != p->p_cred->p_ruid || - strp->oldgid != p->p_cred->p_rgid)) { - - fst = strp->parent; - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - - systrace_msg_ugid(fst, strp); - } else - systrace_unlock(); - - /* Report result from system call */ - systrace_lock(); - strp = p->p_systrace; - if (strp != NULL && ISSET(strp->flags, STR_PROC_SYSCALLRES)) { - size_t argsize; - - CLR(strp->flags, STR_PROC_SYSCALLRES); - fst = strp->parent; - SYSTRACE_LOCK(fst, p); - systrace_unlock(); - DPRINTF(("will ask syscall %lu, strp %p\n", (u_long)code, strp)); - - /* Get the (adjusted) argsize */ - callp = p->p_emul->e_sysent + code; - argsize = callp->sy_argsize; -#ifdef _LP64 - if (p->p_flag & P_32) - argsize = argsize << 1; -#endif - - systrace_msg_result(fst, strp, error, code, argsize, v, retval); - } else { - DPRINTF(("will not ask syscall %lu, strp %p\n", (u_long)code, strp)); - systrace_unlock(); - } -} - -uid_t -systrace_seteuid(struct proc *p, uid_t euid) -{ - struct pcred *pc = p->p_cred; - uid_t oeuid = pc->pc_ucred->cr_uid; - - if (pc->pc_ucred->cr_uid == euid) - return (oeuid); - - /* - * Copy credentials so other references do not see our changes. - */ - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_uid = euid; - p_sugid(p); - - return (oeuid); -} - -gid_t -systrace_setegid(struct proc *p, gid_t egid) -{ - struct pcred *pc = p->p_cred; - gid_t oegid = pc->pc_ucred->cr_gid; - - if (pc->pc_ucred->cr_gid == egid) - return (oegid); - - /* - * Copy credentials so other references do not see our changes. - */ - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_gid = egid; - p_sugid(p); - - return (oegid); -} - -/* Called with fst locked */ - -int -systrace_answer(struct str_process *strp, struct systrace_answer *ans) -{ - int error = 0; - - DPRINTF(("%s: %u: policy %d\n", __func__, - ans->stra_pid, ans->stra_policy)); - - if (!POLICY_VALID(ans->stra_policy)) { - error = EINVAL; - goto out; - } - - /* Check if answer is in sync with us */ - if (ans->stra_seqnr != strp->seqnr) { - error = ESRCH; - goto out; - } - - if ((error = systrace_processready(strp)) != 0) - goto out; - - strp->answer = ans->stra_policy; - strp->error = ans->stra_error; - if (!strp->error) - strp->error = EPERM; - if (ISSET(ans->stra_flags, SYSTR_FLAGS_RESULT)) - SET(strp->flags, STR_PROC_SYSCALLRES); - - /* See if we should elevate privileges for this system call */ - if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEUID)) { - SET(strp->flags, STR_PROC_SETEUID); - strp->seteuid = ans->stra_seteuid; - } - if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEGID)) { - SET(strp->flags, STR_PROC_SETEGID); - strp->setegid = ans->stra_setegid; - } - - - /* Clearing the flag indicates to the process that it woke up */ - CLR(strp->flags, STR_PROC_WAITANSWER); - wakeup(strp); - out: - - return (error); -} - -int -systrace_policy(struct fsystrace *fst, struct systrace_policy *pol) -{ - struct str_policy *strpol; - struct str_process *strp; - - switch(pol->strp_op) { - case SYSTR_POLICY_NEW: - DPRINTF(("%s: new, ents %d\n", __func__, - pol->strp_maxents)); - if (pol->strp_maxents <= 0 || pol->strp_maxents > 1024) - return (EINVAL); - strpol = systrace_newpolicy(fst, pol->strp_maxents); - if (strpol == NULL) - return (ENOBUFS); - pol->strp_num = strpol->nr; - break; - case SYSTR_POLICY_ASSIGN: - DPRINTF(("%s: %d -> pid %d\n", __func__, - pol->strp_num, pol->strp_pid)); - - /* Find right policy by number */ - TAILQ_FOREACH(strpol, &fst->policies, next) - if (strpol->nr == pol->strp_num) - break; - if (strpol == NULL) - return (EINVAL); - - strp = systrace_findpid(fst, pol->strp_pid); - if (strp == NULL) - return (EINVAL); - - /* Check that emulation matches */ - if (strpol->emul && strpol->emul != strp->proc->p_emul) - return (EINVAL); - - if (strp->policy) - systrace_closepolicy(fst, strp->policy); - strp->policy = strpol; - strpol->refcount++; - - /* Record emulation for this policy */ - if (strpol->emul == NULL) - strpol->emul = strp->proc->p_emul; - - break; - case SYSTR_POLICY_MODIFY: - DPRINTF(("%s: %d: code %d -> policy %d\n", __func__, - pol->strp_num, pol->strp_code, pol->strp_policy)); - if (!POLICY_VALID(pol->strp_policy)) - return (EINVAL); - TAILQ_FOREACH(strpol, &fst->policies, next) - if (strpol->nr == pol->strp_num) - break; - if (strpol == NULL) - return (EINVAL); - if (pol->strp_code < 0 || pol->strp_code >= strpol->nsysent) - return (EINVAL); - strpol->sysent[pol->strp_code] = pol->strp_policy; - break; - default: - return (EINVAL); - } - - return (0); -} - -int -systrace_processready(struct str_process *strp) -{ - if (ISSET(strp->flags, STR_PROC_ONQUEUE)) - return (EBUSY); - - if (!ISSET(strp->flags, STR_PROC_WAITANSWER)) - return (EBUSY); - - /* XXX - ignore until systrace knows about lwps. :-( - if (strp->proc->p_stat != LSSLEEP) - return (EBUSY); - */ - return (0); -} - -int -systrace_getcwd(struct fsystrace *fst, struct str_process *strp) -{ -#ifdef __NetBSD__ - struct cwdinfo *mycwdp, *cwdp; -#else - struct filedesc *myfdp, *fdp; -#endif - int error; - - DPRINTF(("%s: %d\n", __func__, strp->pid)); - - error = systrace_processready(strp); - if (error) - return (error); - -#ifdef __NetBSD__ - mycwdp = curproc->p_cwdi; - cwdp = strp->proc->p_cwdi; - if (mycwdp == NULL || cwdp == NULL) - return (EINVAL); - - /* Store our current values */ - fst->fd_pid = strp->pid; - fst->fd_cdir = mycwdp->cwdi_cdir; - fst->fd_rdir = mycwdp->cwdi_rdir; - - if ((mycwdp->cwdi_cdir = cwdp->cwdi_cdir) != NULL) - VREF(mycwdp->cwdi_cdir); - if ((mycwdp->cwdi_rdir = cwdp->cwdi_rdir) != NULL) - VREF(mycwdp->cwdi_rdir); -#else - myfdp = curlwp->p_fd; - fdp = strp->proc->p_fd; - if (myfdp == NULL || fdp == NULL) - return (EINVAL); - - /* Store our current values */ - fst->fd_pid = strp->pid; - fst->fd_cdir = myfdp->fd_cdir; - fst->fd_rdir = myfdp->fd_rdir; - - if ((myfdp->fd_cdir = fdp->fd_cdir) != NULL) - VREF(myfdp->fd_cdir); - if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL) - VREF(myfdp->fd_rdir); -#endif - - return (0); -} - -int -systrace_io(struct str_process *strp, struct systrace_io *io) -{ - struct proc *p = curproc, *t = strp->proc; - struct uio uio; - struct iovec iov; - int error = 0; - - DPRINTF(("%s: %u: %p(%lu)\n", __func__, - io->strio_pid, io->strio_offs, (u_long)io->strio_len)); - - switch (io->strio_op) { - case SYSTR_READ: - uio.uio_rw = UIO_READ; - break; - case SYSTR_WRITE: - uio.uio_rw = UIO_WRITE; - break; - default: - return (EINVAL); - } - - error = systrace_processready(strp); - if (error) - goto out; - - iov.iov_base = io->strio_addr; - iov.iov_len = io->strio_len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(unsigned long)io->strio_offs; - uio.uio_resid = io->strio_len; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_procp = p; - -#ifdef __NetBSD__ - error = process_domem(p, t, &uio); -#else - error = procfs_domem(p, t, NULL, &uio); -#endif - io->strio_len -= uio.uio_resid; - out: - - return (error); -} - -int -systrace_attach(struct fsystrace *fst, pid_t pid) -{ - int error = 0; - struct proc *proc, *p = curproc; - - if ((proc = pfind(pid)) == NULL) { - error = ESRCH; - goto out; - } - - if (ISSET(proc->p_flag, P_INEXEC)) { - error = EAGAIN; - goto out; - } - - /* - * You can't attach to a process if: - * (1) it's the process that's doing the attaching, - */ - if (proc->p_pid == p->p_pid) { - error = EINVAL; - goto out; - } - - /* - * (2) it's a system process - */ - if (ISSET(proc->p_flag, P_SYSTEM)) { - error = EPERM; - goto out; - } - - /* - * (3) it's being traced already - */ - if (ISSET(proc->p_flag, P_SYSTRACE)) { - error = EBUSY; - goto out; - } - - /* - * (4) it's not owned by you, or the last exec - * gave us setuid/setgid privs (unless - * you're root), or... - * - * [Note: once P_SUGID gets set in execve(), it stays - * set until the process does another execve(). Hence - * this prevents a setuid process which revokes its - * special privileges using setuid() from being - * traced. This is good security.] - */ - if ((proc->p_cred->p_ruid != p->p_cred->p_ruid || - ISSET(proc->p_flag, P_SUGID)) && - (error = suser(p->p_ucred, &p->p_acflag)) != 0) - goto out; - - /* - * (5) ...it's init, which controls the security level - * of the entire system, and the system was not - * compiled with permanently insecure mode turned - * on. - */ - if ((proc->p_pid == 1) && (securelevel > -1)) { - error = EPERM; - goto out; - } - - error = systrace_insert_process(fst, proc, NULL); - -#if defined(__NetBSD__) && defined(__HAVE_SYSCALL_INTERN) - /* - * Make sure we're using the version of the syscall handler that - * has systrace hooks. - */ - if (!error) - (*proc->p_emul->e_syscall_intern)(proc); -#endif - out: - return (error); -} - -/* Prepare to replace arguments */ - -int -systrace_preprepl(struct str_process *strp, struct systrace_replace *repl) -{ - size_t len; - int i, ret = 0; - - ret = systrace_processready(strp); - if (ret) - return (ret); - - systrace_replacefree(strp); - - if (repl->strr_nrepl < 0 || repl->strr_nrepl > SYSTR_MAXARGS) - return (EINVAL); - - for (i = 0, len = 0; i < repl->strr_nrepl; i++) { - if (repl->strr_argind[i] < 0 || - repl->strr_argind[i] >= SYSTR_MAXARGS) - return (EINVAL); - if (repl->strr_offlen[i] == 0) - continue; - len += repl->strr_offlen[i]; - if (repl->strr_offlen[i] > SYSTR_MAXREPLEN || - repl->strr_off[i] > SYSTR_MAXREPLEN || - len > SYSTR_MAXREPLEN) - return (EINVAL); - if (repl->strr_offlen[i] + repl->strr_off[i] > len) - return (EINVAL); - } - - /* Make sure that the length adds up */ - if (repl->strr_len != len) - return (EINVAL); - - /* Check against a maximum length */ - if (repl->strr_len > SYSTR_MAXREPLEN) - return (EINVAL); - - strp->replace = (struct systrace_replace *) - malloc(sizeof(struct systrace_replace) + len, M_XDATA, M_WAITOK); - - memcpy(strp->replace, repl, sizeof(struct systrace_replace)); - ret = copyin(repl->strr_base, strp->replace + 1, len); - if (ret) { - free(strp->replace, M_XDATA); - strp->replace = NULL; - return (ret); - } - - /* Adjust the offset */ - repl = strp->replace; - repl->strr_base = (caddr_t)(repl + 1); - - return (0); -} - -/* - * Replace the arguments with arguments from the monitoring process. - */ - -int -systrace_replace(struct str_process *strp, size_t argsize, register_t args[]) -{ - struct proc *p = strp->proc; - struct systrace_replace *repl = strp->replace; - caddr_t sg, kdata, udata, kbase, ubase; - int i, maxarg, ind, ret = 0; - - maxarg = argsize/sizeof(register_t); -#ifdef __NetBSD__ - sg = stackgap_init(p, 0); - ubase = stackgap_alloc(p, &sg, repl->strr_len); -#else - sg = stackgap_init(p->p_emul); - ubase = stackgap_alloc(&sg, repl->strr_len); -#endif - if (ubase == NULL) { - ret = EINVAL; - goto out; - } - - kbase = repl->strr_base; - for (i = 0; i < maxarg && i < repl->strr_nrepl; i++) { - ind = repl->strr_argind[i]; - if (ind < 0 || ind >= maxarg) { - ret = EINVAL; - goto out; - } - if (repl->strr_offlen[i] == 0) { - args[ind] = repl->strr_off[i]; - continue; - } - kdata = kbase + repl->strr_off[i]; - udata = ubase + repl->strr_off[i]; - if (repl->strr_flags[i] & SYSTR_NOLINKS) { - ret = systrace_fname(strp, kdata, repl->strr_offlen[i]); - if (ret != 0) - goto out; - } - if (copyout(kdata, udata, repl->strr_offlen[i])) { - ret = EINVAL; - goto out; - } - - /* Replace the argument with the new address */ - args[ind] = (register_t)(intptr_t)udata; - } - - out: - return (ret); -} - -int -systrace_fname(struct str_process *strp, caddr_t kdata, size_t len) -{ - - if (strp->nfname >= SYSTR_MAXFNAME || len < 2) - return EINVAL; - - strp->fname[strp->nfname] = kdata; - strp->fname[strp->nfname][len - 1] = '\0'; - strp->nfname++; - - return 0; -} - -void -systrace_replacefree(struct str_process *strp) -{ - - if (strp->replace != NULL) { - free(strp->replace, M_XDATA); - strp->replace = NULL; - } - while (strp->nfname > 0) { - strp->nfname--; - strp->fname[strp->nfname] = NULL; - } -} - -void -systrace_namei(struct nameidata *ndp) -{ - struct str_process *strp; - struct fsystrace *fst; - struct componentname *cnp = &ndp->ni_cnd; - size_t i; - - systrace_lock(); - strp = cnp->cn_proc->p_systrace; - if (strp != NULL) { - fst = strp->parent; - SYSTRACE_LOCK(fst, curlwp); - systrace_unlock(); - - for (i = 0; i < strp->nfname; i++) { - if (strcmp(cnp->cn_pnbuf, strp->fname[i]) == 0) { - /* ELOOP if namei() tries to readlink */ - ndp->ni_loopcnt = MAXSYMLINKS; - cnp->cn_flags &= ~FOLLOW; - cnp->cn_flags |= NOFOLLOW; - break; - } - } - SYSTRACE_UNLOCK(fst, curlwp); - } else - systrace_unlock(); -} - -struct str_process * -systrace_findpid(struct fsystrace *fst, pid_t pid) -{ - struct str_process *strp; - struct proc *proc = NULL; - - TAILQ_FOREACH(strp, &fst->processes, next) - if (strp->pid == pid) - break; - - if (strp == NULL) - return (NULL); - - proc = systrace_find(strp); - - return (proc ? strp : NULL); -} - -int -systrace_detach(struct str_process *strp) -{ - struct proc *proc; - struct fsystrace *fst = NULL; - int error = 0; - - DPRINTF(("%s: Trying to detach from %d\n", __func__, strp->pid)); - - if ((proc = systrace_find(strp)) != NULL) { - CLR(proc->p_flag, P_SYSTRACE); - proc->p_systrace = NULL; - } else - error = ESRCH; - - if (ISSET(strp->flags, STR_PROC_WAITANSWER)) { - CLR(strp->flags, STR_PROC_WAITANSWER); - wakeup(strp); - } - - fst = strp->parent; - systrace_wakeup(fst); - - TAILQ_REMOVE(&fst->processes, strp, next); - fst->nprocesses--; - - if (strp->policy) - systrace_closepolicy(fst, strp->policy); - systrace_replacefree(strp); - pool_put(&systr_proc_pl, strp); - - return (error); -} - -void -systrace_closepolicy(struct fsystrace *fst, struct str_policy *policy) -{ - if (--policy->refcount) - return; - - fst->npolicies--; - - if (policy->nsysent) - free(policy->sysent, M_XDATA); - - TAILQ_REMOVE(&fst->policies, policy, next); - - pool_put(&systr_policy_pl, policy); -} - - -int -systrace_insert_process(struct fsystrace *fst, struct proc *proc, - struct str_process **pstrp) -{ - struct str_process *strp; - - strp = pool_get(&systr_proc_pl, PR_NOWAIT); - if (strp == NULL) - return (ENOBUFS); - - memset((caddr_t)strp, 0, sizeof(struct str_process)); - strp->pid = proc->p_pid; - strp->proc = proc; - strp->parent = fst; - - TAILQ_INSERT_TAIL(&fst->processes, strp, next); - fst->nprocesses++; - - proc->p_systrace = strp; - SET(proc->p_flag, P_SYSTRACE); - - /* Pass the new pointer back to the caller */ - if (pstrp != NULL) - *pstrp = strp; - - return (0); -} - -struct str_policy * -systrace_newpolicy(struct fsystrace *fst, int maxents) -{ - struct str_policy *pol; - int i; - - if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) { - struct str_policy *tmp; - - /* Try to find a policy for freeing */ - TAILQ_FOREACH(tmp, &fst->policies, next) { - if (tmp->refcount == 1) - break; - } - - if (tmp == NULL) - return (NULL); - - /* Notify userland about freed policy */ - systrace_msg_policyfree(fst, tmp); - /* Free this policy */ - systrace_closepolicy(fst, tmp); - } - - pol = pool_get(&systr_policy_pl, PR_NOWAIT); - if (pol == NULL) - return (NULL); - - DPRINTF(("%s: allocating %d -> %lu\n", __func__, - maxents, (u_long)maxents * sizeof(int))); - - memset((caddr_t)pol, 0, sizeof(struct str_policy)); - - pol->sysent = (u_char *)malloc(maxents * sizeof(u_char), - M_XDATA, M_WAITOK); - pol->nsysent = maxents; - for (i = 0; i < maxents; i++) - pol->sysent[i] = SYSTR_POLICY_ASK; - - fst->npolicies++; - pol->nr = fst->npolicynr++; - pol->refcount = 1; - - TAILQ_INSERT_TAIL(&fst->policies, pol, next); - - return (pol); -} - -int -systrace_msg_ask(struct fsystrace *fst, struct str_process *strp, - int code, size_t argsize, register_t args[]) -{ - struct str_message msg; - struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask; - int i; - - msg_ask->code = code; - msg_ask->argsize = argsize; - for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++) - msg_ask->args[i] = args[i]; - - return (systrace_make_msg(strp, SYSTR_MSG_ASK, &msg)); -} - -int -systrace_msg_result(struct fsystrace *fst, struct str_process *strp, - int error, int code, size_t argsize, register_t args[], register_t rval[]) -{ - struct str_message msg; - struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask; - int i; - - msg_ask->code = code; - msg_ask->argsize = argsize; - msg_ask->result = error; - for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++) - msg_ask->args[i] = args[i]; - - msg_ask->rval[0] = rval[0]; - msg_ask->rval[1] = rval[1]; - - return (systrace_make_msg(strp, SYSTR_MSG_RES, &msg)); -} - -int -systrace_msg_emul(struct fsystrace *fst, struct str_process *strp) -{ - struct str_message msg; - struct str_msg_emul *msg_emul = &msg.msg_data.msg_emul; - struct proc *p = strp->proc; - - memcpy(msg_emul->emul, p->p_emul->e_name, SYSTR_EMULEN); - - return (systrace_make_msg(strp, SYSTR_MSG_EMUL, &msg)); -} - -int -systrace_msg_ugid(struct fsystrace *fst, struct str_process *strp) -{ - struct str_message msg; - struct str_msg_ugid *msg_ugid = &msg.msg_data.msg_ugid; - struct proc *p = strp->proc; - - msg_ugid->uid = p->p_cred->p_ruid; - msg_ugid->gid = p->p_cred->p_rgid; - - return (systrace_make_msg(strp, SYSTR_MSG_UGID, &msg)); -} - -int -systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg) -{ - struct str_msgcontainer *cont; - struct str_message *msg; - struct fsystrace *fst = strp->parent; - int st; - - cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK); - memset(cont, 0, sizeof(struct str_msgcontainer)); - cont->strp = strp; - - msg = &cont->msg; - - /* Copy the already filled in fields */ - memcpy(&msg->msg_data, &tmsg->msg_data, sizeof(msg->msg_data)); - - /* Add the extra fields to the message */ - msg->msg_seqnr = ++strp->seqnr; - msg->msg_type = type; - msg->msg_pid = strp->pid; - if (strp->policy) - msg->msg_policy = strp->policy->nr; - else - msg->msg_policy = -1; - - SET(strp->flags, STR_PROC_WAITANSWER); - if (ISSET(strp->flags, STR_PROC_ONQUEUE)) - goto out; - - TAILQ_INSERT_TAIL(&fst->messages, cont, next); - SET(strp->flags, STR_PROC_ONQUEUE); - - out: - systrace_wakeup(fst); - - /* Release the lock - XXX */ - SYSTRACE_UNLOCK(fst, strp->proc); - - while (1) { - int f; - f = curlwp->l_flag & L_SA; - curlwp->l_flag &= ~L_SA; - st = tsleep(strp, PWAIT, "systrmsg", 0); - curlwp->l_flag |= f; - if (st != 0) - return (ERESTART); - /* If we detach, then everything is permitted */ - if ((strp = curproc->p_systrace) == NULL) - return (0); - if (!ISSET(strp->flags, STR_PROC_WAITANSWER)) - break; - } - - return (0); -} - -int -systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid) -{ - struct str_msgcontainer *cont; - struct str_message *msg; - struct str_msg_child *msg_child; - - cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK); - memset(cont, 0, sizeof(struct str_msgcontainer)); - cont->strp = strp; - - msg = &cont->msg; - - DPRINTF(("%s: %p: pid %d -> pid %d\n", __func__, - msg, strp->pid, npid)); - - msg_child = &msg->msg_data.msg_child; - - msg->msg_type = SYSTR_MSG_CHILD; - msg->msg_pid = strp->pid; - if (strp->policy) - msg->msg_policy = strp->policy->nr; - else - msg->msg_policy = -1; - msg_child->new_pid = npid; - - TAILQ_INSERT_TAIL(&fst->messages, cont, next); - - systrace_wakeup(fst); - - return (0); -} - -int -systrace_msg_policyfree(struct fsystrace *fst, struct str_policy *strpol) -{ - struct str_msgcontainer *cont; - struct str_message *msg; - - cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK); - memset(cont, 0, sizeof(struct str_msgcontainer)); - - msg = &cont->msg; - - DPRINTF(("%s: free %d\n", __func__, strpol->nr)); - - msg->msg_type = SYSTR_MSG_POLICYFREE; - msg->msg_policy = strpol->nr; - - TAILQ_INSERT_TAIL(&fst->messages, cont, next); - - systrace_wakeup(fst); - - return (0); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_time.c mult-netbsd-3.1/sys/kern/kern_time.c --- NetBSD-3.1/sys/kern/kern_time.c 2005-12-07 09:53:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/kern_time.c 2007-11-18 14:10:51.000000000 +0000 @@ -89,6 +89,8 @@ #include #include +#include + #include #if defined(NFS) || defined(NFSSERVER) @@ -99,7 +101,14 @@ #include -static void timerupcall(struct lwp *, void *); + +POOL_INIT(ptimer_pool, sizeof(struct ptimer), + 0, 0, 0, "ptimerpl", &pool_allocator_nointr); + + +static void +timerupcall(struct lwp *, void *); + /* Time of day and interval timer support. * @@ -134,10 +143,13 @@ struct proc *p = curproc; struct proc *pp = p->p_pptr; log(LOG_WARNING, "pid %d (%s) " - "invoked by uid %d ppid %d (%s) " - "tried to set clock forward to %ld\n", - p->p_pid, p->p_comm, pp->p_ucred->cr_uid, - pp->p_pid, pp->p_comm, (long)tv->tv_sec); + "invoked by uid %d ppid %d (%s) " + "tried to set clock forward to %ld\n", + p->p_pid, p->p_comm, + pp ? pp->p_ucred->cr_uid : 0, + pp ? pp->p_pid : 0, + pp ? pp->p_comm : "(null)", + (long)tv->tv_sec); return (EPERM); } /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/kern_verifiedexec.c mult-netbsd-3.1/sys/kern/kern_verifiedexec.c --- NetBSD-3.1/sys/kern/kern_verifiedexec.c 2005-10-15 18:33:31.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/kern_verifiedexec.c 2007-11-23 17:59:22.000000000 +0000 @@ -59,6 +59,8 @@ int veriexec_verbose = 0; int veriexec_strict = 0; +/* FIXME - instances */ + char *veriexec_fp_names = NULL; unsigned int veriexec_name_max = 0; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/subr_log.c mult-netbsd-3.1/sys/kern/subr_log.c --- NetBSD-3.1/sys/kern/subr_log.c 2003-09-22 13:59:57.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/subr_log.c 2007-11-14 17:12:02.000000000 +0000 @@ -281,7 +281,8 @@ return; selnotify(&logsoftc.sc_selp, 0); if (logsoftc.sc_state & LOG_ASYNC) - fownsignal(logsoftc.sc_pgid, SIGIO, 0, 0, NULL); + /* FIXME - instance */ + fownsignal(proc0.p_inst, logsoftc.sc_pgid, SIGIO, 0, 0, NULL); if (logsoftc.sc_state & LOG_RDWAIT) { wakeup((caddr_t)msgbufp); logsoftc.sc_state &= ~LOG_RDWAIT; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/subr_prf.c mult-netbsd-3.1/sys/kern/subr_prf.c --- NetBSD-3.1/sys/kern/subr_prf.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/subr_prf.c 2007-11-12 16:59:26.000000000 +0000 @@ -449,24 +449,22 @@ * when done, do a "tprintf_close" to drop the handle */ -/* - * tprintf_open: get a tprintf handle on a process "p" - * - * => returns NULL if process can't be printed to - */ tpr_t -tprintf_open(p) - struct proc *p; +tprintf_open(struct proc *p) { + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { SESSHOLD(p->p_session); - return ((tpr_t) p->p_session); + return((tpr_t)p->p_session); } - return ((tpr_t) NULL); + + return((tpr_t)NULL); } + /* * tprintf_close: dispose of a tprintf handle obtained with tprintf_open */ @@ -475,7 +473,6 @@ tprintf_close(sess) tpr_t sess; { - if (sess) SESSRELE((struct session *) sess); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/sys_generic.c mult-netbsd-3.1/sys/kern/sys_generic.c --- NetBSD-3.1/sys/kern/sys_generic.c 2005-02-25 19:56:07.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/sys_generic.c 2007-12-16 14:56:45.000000000 +0000 @@ -62,8 +62,14 @@ #include #include -int selscan(struct proc *, fd_mask *, fd_mask *, int, register_t *); -int pollscan(struct proc *, struct pollfd *, int, register_t *); +#include + +int selscan(struct proc *, fd_mask *, + fd_mask *, int, register_t *); +int pollscan(struct proc *, struct pollfd *, + int, register_t *); + +int selwait, nselcoll; /* @@ -102,6 +108,7 @@ &fp->f_offset, FOF_UPDATE_OFFSET, retval)); } + int dofileread(struct proc *p, int fd, struct file *fp, void *buf, size_t nbyte, off_t *offset, int flags, register_t *retval) @@ -115,6 +122,8 @@ #endif error = 0; + /* FIXME - instances - cross-check credentials? */ + aiov.iov_base = (caddr_t)buf; aiov.iov_len = nbyte; auio.uio_iov = &aiov; @@ -158,6 +167,7 @@ return (error); } + /* * Scatter read system call. */ @@ -193,6 +203,7 @@ &fp->f_offset, FOF_UPDATE_OFFSET, retval)); } + int dofilereadv(struct proc *p, int fd, struct file *fp, const struct iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval) @@ -206,6 +217,8 @@ struct iovec *ktriov; #endif + /* FIXME - instances - cross-check credentials */ + error = 0; #ifdef KTRACE ktriov = NULL; @@ -281,6 +294,7 @@ return (error); } + /* * Write system call */ @@ -311,11 +325,15 @@ FILE_USE(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + /* dofilewrite() will unuse the descriptor for us */ return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), &fp->f_offset, FOF_UPDATE_OFFSET, retval)); } + int dofilewrite(struct proc *p, int fd, struct file *fp, const void *buf, size_t nbyte, off_t *offset, int flags, register_t *retval) @@ -405,6 +423,10 @@ FILE_USE(fp); + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + /* dofilewritev() will unuse the descriptor for us */ return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval)); @@ -649,8 +671,6 @@ } } -int selwait, nselcoll; - /* * Select system call. */ @@ -699,8 +719,13 @@ syscallarg(fd_set *) ex; syscallarg(struct timeval *) tv; } */ * const uap = v; - struct timeval atv, *tv = NULL; - int error; + struct timeval atv, *tv; + int error; + + tv = NULL; + + KASSERT(l); + KASSERT(l->l_inst); if (SCARG(uap, tv)) { error = copyin(SCARG(uap, tv), (caddr_t)&atv, @@ -710,13 +735,16 @@ tv = &atv; } - return selcommon(l, retval, SCARG(uap, nd), SCARG(uap, in), - SCARG(uap, ou), SCARG(uap, ex), tv, NULL); + return(selcommon(l, retval, SCARG(uap, nd), + SCARG(uap, in), SCARG(uap, ou), + SCARG(uap, ex), tv, NULL)); } + int selcommon(struct lwp *l, register_t *retval, int nd, fd_set *u_in, - fd_set *u_ou, fd_set *u_ex, struct timeval *tv, sigset_t *mask) + fd_set *u_ou, fd_set *u_ex, struct timeval *tv, + sigset_t *mask) { struct proc * const p = l->l_proc; caddr_t bits; @@ -817,6 +845,7 @@ return (error); } + int selscan(struct proc *p, fd_mask *ibitp, fd_mask *obitp, int nfd, register_t *retval) @@ -853,6 +882,7 @@ return (0); } + /* * Poll system call. */ @@ -876,6 +906,7 @@ tv, NULL); } + /* * Poll system call. */ @@ -912,6 +943,7 @@ tv, mask); } + int pollcommon(struct lwp *l, register_t *retval, struct pollfd *u_fds, u_int nfds, @@ -995,6 +1027,7 @@ return (error); } + int pollscan(struct proc *p, struct pollfd *fds, int nfd, register_t *retval) { @@ -1002,6 +1035,8 @@ int i, n; struct file *fp; + /* FIXME - instances - cross-check ownership */ + fdp = p->p_fd; n = 0; for (i = 0; i < nfd; i++, fds++) { @@ -1028,6 +1063,7 @@ return (0); } + /*ARGSUSED*/ int seltrue(dev_t dev, int events, struct proc *p) @@ -1036,6 +1072,7 @@ return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); } + /* * Record a select request. */ @@ -1044,33 +1081,48 @@ { struct lwp *l; struct proc *p; + struct inst *i; + u_int myiid; pid_t mypid; + KASSERT(selector); + KASSERT(selector->p_inst); + mypid = selector->p_pid; - if (sip->sel_pid == mypid) + myiid = selector->p_inst->i_uuid; + + if (sip->sel_pid == mypid && sip->sel_iid == myiid) return; - if (sip->sel_pid && (p = pfind(sip->sel_pid))) { + + if (NULL == (i = inst_lookup(sip->sel_iid))) + goto out; + if (sip->sel_pid && (p = pfind(i, sip->sel_pid))) { LIST_FOREACH(l, &p->p_lwps, l_sibling) { if (l->l_wchan == (caddr_t)&selwait) { sip->sel_collision = 1; + inst_release(i); return; } } } + inst_release(i); +out: sip->sel_pid = mypid; + sip->sel_iid = myiid; } + /* * Do a wakeup when a selectable event occurs. */ void -selwakeup(sip) - struct selinfo *sip; +selwakeup(struct selinfo *sip) { - struct lwp *l; - struct proc *p; - int s; + struct lwp *l; + struct proc *p; + int s; + struct inst *i; if (sip->sel_pid == 0) return; @@ -1081,9 +1133,12 @@ wakeup((caddr_t)&selwait); return; } - p = pfind(sip->sel_pid); + + if (NULL == (i = inst_lookup(sip->sel_iid))) + return; + p = pfind(i, sip->sel_pid); sip->sel_pid = 0; - if (p != NULL) { + if (NULL != p) { LIST_FOREACH(l, &p->p_lwps, l_sibling) { SCHED_LOCK(s); if (l->l_wchan == (caddr_t)&selwait) { @@ -1096,4 +1151,6 @@ SCHED_UNLOCK(s); } } + inst_release(i); } + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/sys_pipe.c mult-netbsd-3.1/sys/kern/sys_pipe.c --- NetBSD-3.1/sys/kern/sys_pipe.c 2005-09-14 21:35:05.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/sys_pipe.c 2007-11-23 10:17:19.000000000 +0000 @@ -1,3 +1,4 @@ +/* $Id: sys_pipe.c,v 1.8 2007/11/23 10:17:19 kristaps Exp $ */ /* $NetBSD: sys_pipe.c,v 1.64.2.1 2005/09/14 20:35:05 tron Exp $ */ /*- @@ -109,98 +110,140 @@ #include #include #include +#include #include -/* - * Avoid microtime(9), it's slow. We don't guard the read from time(9) - * with splclock(9) since we don't actually need to be THAT sure the access - * is atomic. +/* + * Limit for direct transfers; we annot limit the amount of kva for + * pipes in general. */ -#define PIPE_TIMESTAMP(tvp) (*(tvp) = time) +#define LIMPIPEKVA (16 * 1024 * 1024) - -/* - * Use this define if you want to disable *fancy* VM things. Expect an - * approx 30% decrease in transfer rate. +/* + * Soft limit for pipe kva, but we don't want to exhaust it on large + * system. */ -/* #define PIPE_NODIRECT */ +#define MAXPIPEKVA (8 * 1024 * 1024) /* - * interfaces to the outside world + * Avoid microtime(9), it's slow. We don't guard the read from time(9) + * with splclock(9) since we don't actually need to be THAT sure the + * access is atomic. */ -static int pipe_read(struct file *fp, off_t *offset, struct uio *uio, - struct ucred *cred, int flags); -static int pipe_write(struct file *fp, off_t *offset, struct uio *uio, - struct ucred *cred, int flags); -static int pipe_close(struct file *fp, struct proc *p); -static int pipe_poll(struct file *fp, int events, struct proc *p); -static int pipe_kqfilter(struct file *fp, struct knote *kn); -static int pipe_stat(struct file *fp, struct stat *sb, struct proc *p); -static int pipe_ioctl(struct file *fp, u_long cmd, void *data, - struct proc *p); - -static const struct fileops pipeops = { - pipe_read, pipe_write, pipe_ioctl, fnullop_fcntl, pipe_poll, - pipe_stat, pipe_close, pipe_kqfilter -}; +#define PIPE_TIMESTAMP(tvp) (*(tvp) = time) -/* - * Default pipe buffer size(s), this can be kind-of large now because pipe - * space is pageable. The pipe code will try to maintain locality of - * reference for performance reasons, so small amounts of outstanding I/O - * will not wipe the cache. +/* + * Limit the number of "big" pipes. */ -#define MINPIPESIZE (PIPE_SIZE/3) -#define MAXPIPESIZE (2*PIPE_SIZE/3) +#define MAXBIGPIPE (32) /* - * Maximum amount of kva for pipes -- this is kind-of a soft limit, but - * is there so that on large systems, we don't exhaust it. + * Default pipe buffer size(s), this can be kind-of large now because + * pipe space is pageable. The pipe code will try to maintain locality + * of reference for performance reasons, so small amounts of outstanding + * I/O will not wipe the cache. */ -#define MAXPIPEKVA (8*1024*1024) -static int maxpipekva = MAXPIPEKVA; +#define MINPIPESIZE (PIPE_SIZE / 3) +#define MAXPIPESIZE (2 * PIPE_SIZE / 3) /* - * Limit for direct transfers, we cannot, of course limit - * the amount of kva for pipes in general though. + * Use this define if you want to disable *fancy* VM things. Expect an + * approx 30% decrease in transfer rate. */ -#define LIMITPIPEKVA (16*1024*1024) -static int limitpipekva = LIMITPIPEKVA; +#if 0 +# define PIPE_NODIRECT +#endif -/* - * Limit the number of "big" pipes - */ -#define LIMITBIGPIPES 32 -static int maxbigpipes = LIMITBIGPIPES; -static int nbigpipe = 0; -/* - * Amount of KVA consumed by pipe buffers. - */ -static int amountpipekva = 0; +struct inst_pipe +{ + int maxpipekva; /* Max (soft-limit) pipe kva. */ + int limpipekva; /* Max transfer kva. */ + int maxbigpipe; /* Max count of big pipes. */ + int nbigpipe; /* Number of allocated bpipes. */ + int amountpipekva; /* Amount of active kva. */ +}; + + +static POOL_INIT(pipe_pool, sizeof(struct pipe), + 0, 0, 0, "pipepl", &pool_allocator_nointr); + MALLOC_DEFINE(M_PIPE, "pipe", "Pipe structures"); -static void pipeclose(struct file *fp, struct pipe *pipe); -static void pipe_free_kmem(struct pipe *pipe); -static int pipe_create(struct pipe **pipep, int allockva); -static int pipelock(struct pipe *pipe, int catch); +static int sysctl_maxpipekva(SYSCTLFN_PROTO); +static int sysctl_limpipekva(SYSCTLFN_PROTO); +static int sysctl_maxbigpipe(SYSCTLFN_PROTO); +static int sysctl_nbigpipe(SYSCTLFN_PROTO); +static int sysctl_amountpipekva(SYSCTLFN_PROTO); + +static int pipe_read(struct file *fp, off_t *offset, + struct uio *uio, struct ucred *cred, + int flags); +static int pipe_write(struct file *fp, off_t *offset, + struct uio *uio, struct ucred *cred, + int flags); +static int pipe_close(struct file *fp, struct proc *p); +static int pipe_poll(struct file *fp, int events, struct proc *p); +static int pipe_kqfilter(struct file *fp, struct knote *kn); +static int pipe_stat(struct file *fp, struct stat *sb, + struct proc *p); +static int pipe_ioctl(struct file *fp, u_long cmd, void *data, + struct proc *p); +static void pipeclose(struct file *fp, struct pipe *pipe); +static void pipe_free_kmem(struct pipe *pipe); +static int pipe_create(struct proc *proc, + struct pipe **pipep, int allockva); +static int pipelock(struct pipe *pipe, int catch); static __inline void pipeunlock(struct pipe *pipe); -static void pipeselwakeup(struct pipe *pipe, struct pipe *sigp, int code); +static void pipeselwakeup(struct pipe *pipe, + struct pipe *sigp, int code); #ifndef PIPE_NODIRECT -static int pipe_direct_write(struct file *fp, struct pipe *wpipe, - struct uio *uio); +static int pipe_direct_write(struct file *fp, struct pipe *wpipe, + struct uio *uio); #endif -static int pipespace(struct pipe *pipe, int size); - +static int pipespace(struct pipe *pipe, int size); #ifndef PIPE_NODIRECT -static int pipe_loan_alloc(struct pipe *, int); -static void pipe_loan_free(struct pipe *); +static int pipe_loan_alloc(struct pipe *, int); +static void pipe_loan_free(struct pipe *); #endif /* PIPE_NODIRECT */ -static POOL_INIT(pipe_pool, sizeof(struct pipe), 0, 0, 0, "pipepl", - &pool_allocator_nointr); + +static const struct fileops pipeops = { + pipe_read, pipe_write, pipe_ioctl, + fnullop_fcntl, pipe_poll, pipe_stat, + pipe_close, pipe_kqfilter +}; + + +int +inst_pipe_alloc(inst_pipe_t *p, int flags) +{ + struct inst_pipe *i; + + KASSERT(p); + i = malloc(sizeof(struct inst_pipe), M_INST, flags); + if (NULL == i) + return(0); + memset(i, 0, sizeof(struct inst_pipe)); + + i->maxpipekva = MAXPIPEKVA; + i->limpipekva = LIMPIPEKVA; + i->maxbigpipe = MAXBIGPIPE; + + *p = i; + return(1); +} + + +void +inst_pipe_free(inst_pipe_t p) +{ + KASSERT(p); + free(p, M_INST); +} + /* * The pipe system call for the DTYPE_PIPE type of pipes @@ -208,19 +251,20 @@ /* ARGSUSED */ int -sys_pipe(l, v, retval) - struct lwp *l; - void *v; - register_t *retval; -{ - struct file *rf, *wf; - struct pipe *rpipe, *wpipe; - int fd, error; - struct proc *p; +sys_pipe(struct lwp *l, void *v, register_t *retval) +{ + struct file *rf, *wf; + struct pipe *rpipe, *wpipe; + int fd, error; + struct proc *p; p = l->l_proc; rpipe = wpipe = NULL; - if (pipe_create(&rpipe, 1) || pipe_create(&wpipe, 0)) { + + KASSERT(p); + KASSERT(p->p_inst); + + if (pipe_create(p, &rpipe, 1) || pipe_create(p, &wpipe, 0)) { pipeclose(NULL, rpipe); pipeclose(NULL, wpipe); return (ENFILE); @@ -234,18 +278,18 @@ * file descriptor races if we block in the second falloc(). */ - error = falloc(p, &rf, &fd); - if (error) + if ((error = falloc(p, &rf, &fd))) goto free2; + retval[0] = fd; rf->f_flag = FREAD; rf->f_type = DTYPE_PIPE; rf->f_data = (caddr_t)rpipe; rf->f_ops = &pipeops; - error = falloc(p, &wf, &fd); - if (error) + if ((error = falloc(p, &wf, &fd))) goto free3; + retval[1] = fd; wf->f_flag = FWRITE; wf->f_type = DTYPE_PIPE; @@ -260,10 +304,12 @@ FILE_UNUSE(rf, p); FILE_UNUSE(wf, p); return (0); + free3: FILE_UNUSE(rf, p); ffree(rf); fdremove(p->p_fd, retval[0]); + free2: pipeclose(NULL, wpipe); pipeclose(NULL, rpipe); @@ -271,18 +317,20 @@ return (error); } + /* - * Allocate kva for pipe circular buffer, the space is pageable - * This routine will 'realloc' the size of a pipe safely, if it fails - * it will retain the old buffer. - * If it fails it will return ENOMEM. + * Allocate kva for pipe circular buffer, the space is pageable This + * routine will 'realloc' the size of a pipe safely, if it fails it will + * retain the old buffer. If it fails it will return ENOMEM. */ static int -pipespace(pipe, size) - struct pipe *pipe; - int size; +pipespace(struct pipe *pipe, int size) { - caddr_t buffer; + caddr_t buffer; + + KASSERT(pipe); + KASSERT(pipe->pipe_inst); + /* * Allocate pageable virtual address space. Physical memory is * allocated on demand. @@ -298,26 +346,30 @@ pipe->pipe_buffer.in = 0; pipe->pipe_buffer.out = 0; pipe->pipe_buffer.cnt = 0; - amountpipekva += pipe->pipe_buffer.size; + pipe->pipe_inst->i_pipe->amountpipekva += pipe->pipe_buffer.size; return (0); } + /* * Initialize and allocate VM and memory for pipe. */ static int -pipe_create(pipep, allockva) - struct pipe **pipep; - int allockva; +pipe_create(struct proc *p, struct pipe **pipep, int allockva) { - struct pipe *pipe; - int error; + struct pipe *pipe; + int error; - pipe = *pipep = pool_get(&pipe_pool, PR_WAITOK); + KASSERT(p); + KASSERT(p->p_inst); - /* Initialize */ + pipe = *pipep = pool_get(&pipe_pool, PR_WAITOK); memset(pipe, 0, sizeof(struct pipe)); + pipe->pipe_state = PIPE_SIGNALR; + pipe->pipe_inst = p->p_inst; + inst_hold(p->p_inst); + p->p_inst->i_npipes++; PIPE_TIMESTAMP(&pipe->pipe_ctime); pipe->pipe_atime = pipe->pipe_ctime; @@ -333,16 +385,16 @@ /* - * Lock a pipe for I/O, blocking other access - * Called with pipe spin lock held. - * Return with pipe spin lock released on success. + * Lock a pipe for I/O, blocking other access Called with pipe spin lock + * held. Return with pipe spin lock released on success. */ static int -pipelock(pipe, catch) - struct pipe *pipe; - int catch; +pipelock(struct pipe *pipe, int catch) { - int error; + int error; + + KASSERT(pipe); + KASSERT(pipe->pipe_inst); LOCK_ASSERT(simple_lock_held(&pipe->pipe_slock)); @@ -373,38 +425,47 @@ * beneficial. */ (void) ltsleep(&lbolt, PSOCK, "rstrtpipelock", hz, - &pipe->pipe_slock); + &pipe->pipe_slock); } return (error); } + /* * unlock a pipe I/O lock */ static __inline void -pipeunlock(pipe) - struct pipe *pipe; +pipeunlock(struct pipe *pipe) { - lockmgr(&pipe->pipe_lock, LK_RELEASE, NULL); } + /* * Select/poll wakup. This also sends SIGIO to peer connected to * 'sigpipe' side of pipe. */ static void -pipeselwakeup(selp, sigp, code) - struct pipe *selp, *sigp; - int code; +pipeselwakeup(struct pipe *selp, struct pipe *sigp, int code) { - int band; + int band; + + KASSERT(selp); + KASSERT(selp->pipe_inst); selnotify(&selp->pipe_sel, NOTE_SUBMIT); if (sigp == NULL || (sigp->pipe_state & PIPE_ASYNC) == 0) return; + KASSERT(sigp->pipe_inst); + + if (selp->pipe_inst != sigp->pipe_inst) + printf("error: selp->pipe_inst = %d, " + "sigp->pipe_inst = %d\n", + selp->pipe_inst->i_uuid, + sigp->pipe_inst->i_uuid); + switch (code) { case POLL_IN: band = POLLIN|POLLRDNORM; @@ -428,24 +489,33 @@ break; } - fownsignal(sigp->pipe_pgid, SIGIO, code, band, selp); + fownsignal(sigp->pipe_inst, sigp->pipe_pgid, + SIGIO, code, band, selp); } + /* ARGSUSED */ static int -pipe_read(fp, offset, uio, cred, flags) - struct file *fp; - off_t *offset; - struct uio *uio; - struct ucred *cred; - int flags; -{ - struct pipe *rpipe = (struct pipe *) fp->f_data; - struct pipebuf *bp = &rpipe->pipe_buffer; - int error; - size_t nread = 0; - size_t size; - size_t ocnt; +pipe_read(struct file *fp, off_t *offset, struct uio *uio, + struct ucred *cred, int flags) +{ + struct pipe *rpipe; + struct pipebuf *bp; + int error; + size_t nread, size, ocnt; + + nread = 0; + rpipe = (struct pipe *) fp->f_data; + bp = &rpipe->pipe_buffer; + + KASSERT(rpipe->pipe_inst); + KASSERT(cred->cr_inst); + + if (rpipe->pipe_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: rpipe->pipe_inst = %d, " + "cred->cr_inst->i_uuid = %d\n", + rpipe->pipe_inst->i_uuid, + cred->cr_inst->i_uuid); PIPE_LOCK(rpipe); ++rpipe->pipe_busy; @@ -620,70 +690,90 @@ return (error); } + #ifndef PIPE_NODIRECT /* * Allocate structure for loan transfer. */ static int -pipe_loan_alloc(wpipe, npages) - struct pipe *wpipe; - int npages; +pipe_loan_alloc(struct pipe *wpipe, int npages) { - vsize_t len; + vsize_t len; + + KASSERT(wpipe); + KASSERT(wpipe->pipe_inst); len = (vsize_t)npages << PAGE_SHIFT; wpipe->pipe_map.kva = uvm_km_valloc_wait(kernel_map, len); if (wpipe->pipe_map.kva == 0) return (ENOMEM); - amountpipekva += len; + wpipe->pipe_inst->i_pipe->amountpipekva += len; wpipe->pipe_map.npages = npages; wpipe->pipe_map.pgs = malloc(npages * sizeof(struct vm_page *), M_PIPE, M_WAITOK); return (0); } + /* * Free resources allocated for loan transfer. */ static void -pipe_loan_free(wpipe) - struct pipe *wpipe; +pipe_loan_free(struct pipe *wpipe) { - vsize_t len; + vsize_t len; + + KASSERT(wpipe); + KASSERT(wpipe->pipe_inst); len = (vsize_t)wpipe->pipe_map.npages << PAGE_SHIFT; uvm_km_free(kernel_map, wpipe->pipe_map.kva, len); wpipe->pipe_map.kva = 0; - amountpipekva -= len; + wpipe->pipe_inst->i_pipe->amountpipekva -= len; free(wpipe->pipe_map.pgs, M_PIPE); wpipe->pipe_map.pgs = NULL; } + /* - * NetBSD direct write, using uvm_loan() mechanism. - * This implements the pipe buffer write mechanism. Note that only - * a direct write OR a normal pipe write can be pending at any given time. - * If there are any characters in the pipe buffer, the direct write will - * be deferred until the receiving process grabs all of the bytes from - * the pipe buffer. Then the direct mapping write is set-up. + * NetBSD direct write, using uvm_loan() mechanism. This implements the + * pipe buffer write mechanism. Note that only a direct write OR a + * normal pipe write can be pending at any given time. If there are any + * characters in the pipe buffer, the direct write will be deferred + * until the receiving process grabs all of the bytes from the pipe + * buffer. Then the direct mapping write is set-up. * * Called with the long-term pipe lock held. */ static int -pipe_direct_write(fp, wpipe, uio) - struct file *fp; - struct pipe *wpipe; - struct uio *uio; -{ - int error, npages, j; - struct vm_page **pgs; - vaddr_t bbase, kva, base, bend; - vsize_t blen, bcnt; - voff_t bpos; +pipe_direct_write(struct file *fp, struct pipe *wpipe, + struct uio *uio) +{ + int error, npages, j, maxpipekva; + struct vm_page **pgs; + vaddr_t bbase, kva, base, bend; + vsize_t blen, bcnt; + voff_t bpos; + KASSERT(wpipe); + KASSERT(wpipe->pipe_inst); KASSERT(wpipe->pipe_map.cnt == 0); + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + + maxpipekva = wpipe->pipe_inst->i_pipe->maxpipekva; + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != wpipe->pipe_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "wpipe->pipe_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + wpipe->pipe_inst->i_uuid); + /* * Handle first PIPE_CHUNK_SIZE bytes of buffer. Deal with buffers * not aligned to PAGE_SIZE. @@ -785,7 +875,8 @@ pmap_kremove(wpipe->pipe_map.kva, blen); uvm_unloan(pgs, npages, UVM_LOAN_TOPAGE); } - if (error || amountpipekva > maxpipekva) + if (error || wpipe->pipe_inst->i_pipe->amountpipekva > + maxpipekva) pipe_loan_free(wpipe); if (error) { @@ -820,21 +911,37 @@ } #endif /* !PIPE_NODIRECT */ + static int -pipe_write(fp, offset, uio, cred, flags) - struct file *fp; - off_t *offset; - struct uio *uio; - struct ucred *cred; - int flags; -{ - struct pipe *wpipe, *rpipe; - struct pipebuf *bp; - int error; +pipe_write(struct file *fp, off_t *offset, struct uio *uio, + struct ucred *cred, int flags) +{ + struct pipe *wpipe, *rpipe; + struct pipebuf *bp; + int error, limpipekva, maxbigpipe, amtpipekva; /* We want to write to our peer */ rpipe = (struct pipe *) fp->f_data; + KASSERT(rpipe); + KASSERT(rpipe->pipe_inst); + KASSERT(fp); + KASSERT(fp->f_cred); + + KASSERT(cred); + KASSERT(cred->cr_inst); + + limpipekva = rpipe->pipe_inst->i_pipe->limpipekva; + maxbigpipe = rpipe->pipe_inst->i_pipe->maxbigpipe; + amtpipekva = rpipe->pipe_inst->i_pipe->amountpipekva; + + /* FIXME - instance protection */ + + if (fp->f_cred->cr_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "cred->cr_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + cred->cr_inst->i_uuid); retry: error = 0; PIPE_LOCK(rpipe); @@ -854,10 +961,18 @@ error = EPIPE; } + /* FIXME - instance protection */ + PIPE_UNLOCK(rpipe); if (error != 0) return (error); + if (wpipe->pipe_inst->i_uuid != rpipe->pipe_inst->i_uuid) + printf("error: wpipe->pipe_inst = %d, " + "rpipe->pipe_inst = %d\n", + wpipe->pipe_inst->i_uuid, + rpipe->pipe_inst->i_uuid); + ++wpipe->pipe_busy; /* Aquire the long-term pipe lock */ @@ -878,14 +993,14 @@ * If it is advantageous to resize the pipe buffer, do so. */ if ((uio->uio_resid > PIPE_SIZE) && - (nbigpipe < maxbigpipes) && + (wpipe->pipe_inst->i_pipe->nbigpipe < maxbigpipe) && #ifndef PIPE_NODIRECT (wpipe->pipe_state & PIPE_DIRECTW) == 0 && #endif (bp->size <= PIPE_SIZE) && (bp->cnt == 0)) { if (pipespace(wpipe, BIG_PIPE_SIZE) == 0) - nbigpipe++; + wpipe->pipe_inst->i_pipe->nbigpipe++; } while (uio->uio_resid) { @@ -928,7 +1043,7 @@ */ if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) && (fp->f_flag & FNONBLOCK) == 0 && - (wpipe->pipe_map.kva || (amountpipekva < limitpipekva))) { + (wpipe->pipe_map.kva || (amtpipekva < limpipekva))) { error = pipe_direct_write(fp, wpipe, uio); /* @@ -1097,17 +1212,38 @@ return (error); } + /* * we implement a very minimal set of ioctls for compatibility with sockets. */ int -pipe_ioctl(fp, cmd, data, p) - struct file *fp; - u_long cmd; - void *data; - struct proc *p; +pipe_ioctl(struct file *fp, u_long cmd, void *data, struct proc *p) { - struct pipe *pipe = (struct pipe *)fp->f_data; + struct pipe *pipe; + + pipe = (struct pipe *)fp->f_data; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(p); + KASSERT(p->p_inst); + KASSERT(pipe); + KASSERT(pipe->pipe_inst); + + /* FIXME - instance protection */ + + if (fp->f_cred->cr_inst->i_uuid != p->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "p->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + p->p_inst->i_uuid); + + if (pipe->pipe_inst->i_uuid != p->p_inst->i_uuid) + printf("error: pipe->pipe_inst = %d, " + "p->p_inst = %d\n", + pipe->pipe_inst->i_uuid, + p->p_inst->i_uuid); switch (cmd) { @@ -1179,20 +1315,52 @@ return (EPASSTHROUGH); } + int -pipe_poll(fp, events, td) - struct file *fp; - int events; - struct proc *td; -{ - struct pipe *rpipe = (struct pipe *)fp->f_data; - struct pipe *wpipe; - int eof = 0; - int revents = 0; +pipe_poll(struct file *fp, int events, struct proc *td) +{ + struct pipe *rpipe, *wpipe; + int eof; + int revents; + + eof = revents = 0; + rpipe = (struct pipe *)fp->f_data; + + /* FIXME - instance protection */ + + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(td); + KASSERT(td->p_inst); + KASSERT(rpipe); + KASSERT(rpipe->pipe_inst); + + if (fp->f_cred->cr_inst->i_uuid != td->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "td->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + td->p_inst->i_uuid); + + if (rpipe->pipe_inst->i_uuid != td->p_inst->i_uuid) + printf("error: rpipe->pipe_inst = %d, " + "td->p_inst = %d\n", + rpipe->pipe_inst->i_uuid, + td->p_inst->i_uuid); retry: PIPE_LOCK(rpipe); wpipe = rpipe->pipe_peer; + + if (wpipe) { + KASSERT(wpipe->pipe_inst); + if (wpipe->pipe_inst->i_uuid != + rpipe->pipe_inst->i_uuid) + printf("error: rpipe->pipe_inst = %d, " + "wpipe->p_inst = %d\n", + rpipe->pipe_inst->i_uuid, + wpipe->pipe_inst->i_uuid); + } + if (wpipe != NULL && simple_lock_try(&wpipe->pipe_slock) == 0) { /* Deal with race for peer */ PIPE_UNLOCK(rpipe); @@ -1239,13 +1407,33 @@ return (revents); } + static int -pipe_stat(fp, ub, td) - struct file *fp; - struct stat *ub; - struct proc *td; +pipe_stat(struct file *fp, struct stat *ub, struct proc *td) { - struct pipe *pipe = (struct pipe *)fp->f_data; + struct pipe *pipe; + + pipe = (struct pipe *)fp->f_data; + + /* FIXME - instance protection */ + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(td); + KASSERT(td->p_inst); + + if (td->p_inst->i_uuid != fp->f_cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "td->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + td->p_inst->i_uuid); + + if (td->p_inst->i_uuid != pipe->pipe_inst->i_uuid) + printf("error: pipe->pipe_inst = %d, " + "td->p_inst = %d\n", + pipe->pipe_inst->i_uuid, + td->p_inst->i_uuid); memset((caddr_t)ub, 0, sizeof(*ub)); ub->st_mode = S_IFIFO | S_IRUSR | S_IWUSR; @@ -1260,34 +1448,58 @@ ub->st_uid = fp->f_cred->cr_uid; ub->st_gid = fp->f_cred->cr_gid; /* - * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, st_gen. - * XXX (st_dev, st_ino) should be unique. + * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, + * st_gen. XXX (st_dev, st_ino) should be unique. */ return (0); } + /* ARGSUSED */ static int -pipe_close(fp, td) - struct file *fp; - struct proc *td; +pipe_close(struct file *fp, struct proc *td) { - struct pipe *pipe = (struct pipe *)fp->f_data; + struct pipe *pipe; + + pipe = (struct pipe *)fp->f_data; + KASSERT(pipe); + KASSERT(pipe->pipe_inst); + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(td); + KASSERT(td->p_inst); + + if (td->p_inst->i_uuid != fp->f_cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "td->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + td->p_inst->i_uuid); + + if (td->p_inst->i_uuid != pipe->pipe_inst->i_uuid) + printf("error: pipe->pipe_inst = %d, " + "td->p_inst = %d\n", + pipe->pipe_inst->i_uuid, + td->p_inst->i_uuid); + fp->f_data = NULL; pipeclose(fp, pipe); return (0); } + static void -pipe_free_kmem(pipe) - struct pipe *pipe; +pipe_free_kmem(struct pipe *pipe) { + KASSERT(pipe); + KASSERT(pipe->pipe_inst); if (pipe->pipe_buffer.buffer != NULL) { if (pipe->pipe_buffer.size > PIPE_SIZE) - --nbigpipe; - amountpipekva -= pipe->pipe_buffer.size; + --pipe->pipe_inst->i_pipe->nbigpipe; + pipe->pipe_inst->i_pipe->amountpipekva -= + pipe->pipe_buffer.size; uvm_km_free(kernel_map, (vaddr_t)pipe->pipe_buffer.buffer, pipe->pipe_buffer.size); @@ -1304,19 +1516,29 @@ #endif /* !PIPE_NODIRECT */ } + /* * shutdown the pipe */ static void -pipeclose(fp, pipe) - struct file *fp; - struct pipe *pipe; +pipeclose(struct file *fp, struct pipe *pipe) { - struct pipe *ppipe; + struct pipe *ppipe; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); if (pipe == NULL) return; + KASSERT(pipe->pipe_inst); + if (pipe->pipe_inst->i_uuid != fp->f_cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "pipe->pipe_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + pipe->pipe_inst->i_uuid); + retry: PIPE_LOCK(pipe); @@ -1353,17 +1575,21 @@ (void)lockmgr(&pipe->pipe_lock, LK_DRAIN | LK_INTERLOCK, &pipe->pipe_slock); - /* - * free resources - */ + pipe->pipe_inst->i_npipes--; + inst_release(pipe->pipe_inst); pipe_free_kmem(pipe); pool_put(&pipe_pool, pipe); } + static void filt_pipedetach(struct knote *kn) { - struct pipe *pipe = (struct pipe *)kn->kn_fp->f_data; + struct pipe *pipe; + + pipe = (struct pipe *)kn->kn_fp->f_data; + KASSERT(pipe); + KASSERT(pipe->pipe_inst); switch(kn->kn_filter) { case EVFILT_WRITE: @@ -1391,12 +1617,28 @@ PIPE_UNLOCK(pipe); } + /*ARGSUSED*/ static int filt_piperead(struct knote *kn, long hint) { - struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data; - struct pipe *wpipe = rpipe->pipe_peer; + struct pipe *rpipe, *wpipe; + + rpipe = (struct pipe *)kn->kn_fp->f_data; + wpipe = rpipe->pipe_peer; + + KASSERT(rpipe); + KASSERT(rpipe->pipe_inst); + KASSERT(wpipe); + KASSERT(wpipe->pipe_inst); + + /* FIXME - instances - cross-check */ + + if (rpipe->pipe_inst->i_uuid != wpipe->pipe_inst->i_uuid) + printf("error: rpipe->pipe_inst = %d, " + "wpipe->pipe_inst = %d\n", + rpipe->pipe_inst->i_uuid, + wpipe->pipe_inst->i_uuid); if ((hint & NOTE_SUBMIT) == 0) PIPE_LOCK(rpipe); @@ -1417,6 +1659,7 @@ return (kn->kn_data > 0); } + /*ARGSUSED*/ static int filt_pipewrite(struct knote *kn, long hint) @@ -1424,6 +1667,23 @@ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data; struct pipe *wpipe = rpipe->pipe_peer; + rpipe = (struct pipe *)kn->kn_fp->f_data; + wpipe = rpipe->pipe_peer; + + KASSERT(rpipe); + KASSERT(rpipe->pipe_inst); + KASSERT(wpipe); + KASSERT(wpipe->pipe_inst); + + /* FIXME - instances - cross-check */ + + if (rpipe->pipe_inst->i_uuid != wpipe->pipe_inst->i_uuid) + printf("error: rpipe->pipe_inst = %d, " + "wpipe->pipe_inst = %d\n", + rpipe->pipe_inst->i_uuid, + wpipe->pipe_inst->i_uuid); + + if ((hint & NOTE_SUBMIT) == 0) PIPE_LOCK(rpipe); /* XXXSMP: race for peer */ @@ -1443,18 +1703,23 @@ return (kn->kn_data >= PIPE_BUF); } + static const struct filterops pipe_rfiltops = { 1, NULL, filt_pipedetach, filt_piperead }; static const struct filterops pipe_wfiltops = { 1, NULL, filt_pipedetach, filt_pipewrite }; + /*ARGSUSED*/ static int pipe_kqfilter(struct file *fp, struct knote *kn) { - struct pipe *pipe; + struct pipe *pipe; pipe = (struct pipe *)kn->kn_fp->f_data; + KASSERT(pipe); + KASSERT(pipe->pipe_inst); + switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &pipe_rfiltops; @@ -1479,6 +1744,7 @@ return (0); } + /* * Handle pipe sysctls. */ @@ -1502,31 +1768,56 @@ CTLTYPE_INT, "maxkvasz", SYSCTL_DESCR("Maximum amount of kernel memory to be " "used for pipes"), - NULL, 0, &maxpipekva, 0, + sysctl_maxpipekva, 0, NULL, 0, CTL_KERN, KERN_PIPE, KERN_PIPE_MAXKVASZ, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "maxloankvasz", SYSCTL_DESCR("Limit for direct transfers via page loan"), - NULL, 0, &limitpipekva, 0, + sysctl_limpipekva, 0, NULL, 0, CTL_KERN, KERN_PIPE, KERN_PIPE_LIMITKVA, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "maxbigpipes", SYSCTL_DESCR("Maximum number of \"big\" pipes"), - NULL, 0, &maxbigpipes, 0, + sysctl_maxbigpipe, 0, NULL, 0, CTL_KERN, KERN_PIPE, KERN_PIPE_MAXBIGPIPES, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_INT, "nbigpipes", SYSCTL_DESCR("Number of \"big\" pipes"), - NULL, 0, &nbigpipe, 0, + sysctl_nbigpipe, 0, NULL, 0, CTL_KERN, KERN_PIPE, KERN_PIPE_NBIGPIPES, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_INT, "kvasize", SYSCTL_DESCR("Amount of kernel memory consumed by pipe " "buffers"), - NULL, 0, &amountpipekva, 0, + sysctl_amountpipekva, 0, NULL, 0, CTL_KERN, KERN_PIPE, KERN_PIPE_KVASIZE, CTL_EOL); } + + +#define sysctl_impl(name, val) \ +static int \ +name(SYSCTLFN_ARGS) \ +{ \ + int nval, error; \ + struct sysctlnode node; \ + \ + nval = l->l_inst->i_pipe->val; \ + node = *rnode; \ + node.sysctl_data = &nval; \ + error = sysctl_lookup(SYSCTLFN_CALL(&node)); \ + if (error || newp == NULL) \ + return (error); \ + l->l_inst->i_pipe->val = nval; \ + return (error); \ +} + +sysctl_impl(sysctl_maxpipekva, maxpipekva) +sysctl_impl(sysctl_limpipekva, limpipekva) +sysctl_impl(sysctl_maxbigpipe, maxbigpipe) +sysctl_impl(sysctl_nbigpipe, nbigpipe) +sysctl_impl(sysctl_amountpipekva, amountpipekva) + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/sys_process.c mult-netbsd-3.1/sys/kern/sys_process.c --- NetBSD-3.1/sys/kern/sys_process.c 2006-10-26 11:23:11.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/sys_process.c 2007-11-23 10:17:19.000000000 +0000 @@ -105,6 +105,8 @@ #include #include +#include + #include #include @@ -139,13 +141,16 @@ int s, error, write, tmp; char *path; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + /* "A foolish consistency..." XXX */ if (SCARG(uap, req) == PT_TRACE_ME) t = p; else { /* Find the process we're supposed to be operating on. */ - if ((t = pfind(SCARG(uap, pid))) == NULL) + if ((t = pfind(p->p_inst, SCARG(uap, pid))) == NULL) return (ESRCH); } @@ -194,7 +199,7 @@ * of the entire system, and the system was not * compiled with permanently insecure mode turned on */ - if (t == initproc && securelevel > -1) + if (t == p->p_inst->i_initproc && securelevel > -1) return (EPERM); /* @@ -417,15 +422,16 @@ if (SCARG(uap, req) == PT_DETACH) { /* give process back to original parent or init */ - s = proclist_lock_write(); - if (t->p_opptr != t->p_pptr) { + s = proclist_lock_write(p->p_inst); + if (t->p_opptr && t->p_opptr != t->p_pptr) { struct proc *pp = t->p_opptr; - proc_reparent(t, pp ? pp : initproc); + proc_reparent(t, pp ? pp : + p->p_inst->i_initproc); } /* not being traced any more */ t->p_opptr = NULL; - proclist_unlock_write(s); + proclist_unlock_write(p->p_inst, s); CLR(t->p_flag, P_TRACED|P_WAITED); } @@ -469,13 +475,13 @@ * Stop the target. */ SET(t->p_flag, P_TRACED); - s = proclist_lock_write(); + s = proclist_lock_write(p->p_inst); t->p_opptr = t->p_pptr; - if (t->p_pptr != p) { + if (t->p_pptr && t->p_pptr != p) { t->p_pptr->p_flag |= P_CHTRACED; proc_reparent(t, p); } - proclist_unlock_write(s); + proclist_unlock_write(p->p_inst, s); SCARG(uap, data) = SIGSTOP; goto sendsig; @@ -784,7 +790,7 @@ * of the entire system, and the system was not * compiled with permanetly insecure mode turned on. */ - if (t == initproc && securelevel > -1) + if (t == p->p_inst->i_initproc && securelevel > -1) return (EPERM); /* diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/sys_socket.c mult-netbsd-3.1/sys/kern/sys_socket.c --- NetBSD-3.1/sys/kern/sys_socket.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/sys_socket.c 2007-11-18 18:59:49.000000000 +0000 @@ -45,51 +45,120 @@ #include #include #include +#include #include #include + struct fileops socketops = { soo_read, soo_write, soo_ioctl, soo_fcntl, soo_poll, soo_stat, soo_close, soo_kqfilter }; + /* ARGSUSED */ int -soo_read(fp, offset, uio, cred, flags) - struct file *fp; - off_t *offset; - struct uio *uio; - struct ucred *cred; - int flags; +soo_read(struct file *fp, off_t *offset, struct uio *uio, + struct ucred *cred, int flags) { - struct socket *so = (struct socket *) fp->f_data; + struct socket *so; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(cred); + KASSERT(cred->cr_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "cred->cr_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + cred->cr_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: so->so_inst = %d, " + "cred->cr_inst = %d\n", + so->so_inst->i_uuid, + cred->cr_inst->i_uuid); + return ((*so->so_receive)(so, (struct mbuf **)0, - uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0)); + uio, (struct mbuf **)0, + (struct mbuf **)0, (int *)0)); } + /* ARGSUSED */ int -soo_write(fp, offset, uio, cred, flags) - struct file *fp; - off_t *offset; - struct uio *uio; - struct ucred *cred; - int flags; +soo_write(struct file *fp, off_t *offset, struct uio *uio, + struct ucred *cred, int flags) { - struct socket *so = (struct socket *) fp->f_data; + struct socket *so; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(cred); + KASSERT(cred->cr_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "cred->cr_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + cred->cr_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != cred->cr_inst->i_uuid) + printf("error: so->so_inst = %d, " + "cred->cr_inst = %d\n", + so->so_inst->i_uuid, + cred->cr_inst->i_uuid); + return ((*so->so_send)(so, (struct mbuf *)0, - uio, (struct mbuf *)0, (struct mbuf *)0, 0, uio->uio_procp)); + uio, (struct mbuf *)0, + (struct mbuf *)0, 0, uio->uio_procp)); } + int -soo_ioctl(fp, cmd, data, p) - struct file *fp; - u_long cmd; - void *data; - struct proc *p; +soo_ioctl(struct file *fp, u_long cmd, void *data, struct proc *p) { - struct socket *so = (struct socket *)fp->f_data; + struct socket *so; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(p); + KASSERT(p->p_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != p->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "p->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + p->p_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != p->p_inst->i_uuid) + printf("error: so->so_inst = %d, " + "p->p_inst = %d\n", + so->so_inst->i_uuid, + p->p_inst->i_uuid); switch (cmd) { @@ -161,12 +230,9 @@ (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0, p)); } + int -soo_fcntl(fp, cmd, data, p) - struct file *fp; - u_int cmd; - void *data; - struct proc *p; +soo_fcntl(struct file *fp, u_int cmd, void *data, struct proc *p) { if (cmd == F_SETFL) return (0); @@ -174,15 +240,40 @@ return (EOPNOTSUPP); } + int -soo_poll(fp, events, p) - struct file *fp; - int events; - struct proc *p; -{ - struct socket *so = (struct socket *)fp->f_data; - int revents = 0; - int s = splsoftnet(); +soo_poll(struct file *fp, int events, struct proc *p) +{ + struct socket *so; + int s, revents; + + revents = 0; + s = splsoftnet(); + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(p); + KASSERT(p->p_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != p->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "p->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + p->p_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != p->p_inst->i_uuid) + printf("error: so->so_inst = %d, " + "p->p_inst = %d\n", + so->so_inst->i_uuid, + p->p_inst->i_uuid); + if (events & (POLLIN | POLLRDNORM)) if (soreadable(so)) @@ -212,30 +303,80 @@ return (revents); } + int -soo_stat(fp, ub, p) - struct file *fp; - struct stat *ub; - struct proc *p; +soo_stat(struct file *fp, struct stat *ub, struct proc *p) { - struct socket *so = (struct socket *)fp->f_data; + struct socket *so; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(p); + KASSERT(p->p_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != p->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "p->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + p->p_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != p->p_inst->i_uuid) + printf("error: so->so_inst = %d, " + "p->p_inst = %d\n", + so->so_inst->i_uuid, + p->p_inst->i_uuid); memset((caddr_t)ub, 0, sizeof(*ub)); ub->st_mode = S_IFSOCK; return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE, - (struct mbuf *)ub, (struct mbuf *)0, (struct mbuf *)0, p)); + (struct mbuf *)ub, (struct mbuf *)0, + (struct mbuf *)0, p)); } + /* ARGSUSED */ int -soo_close(fp, p) - struct file *fp; - struct proc *p; +soo_close(struct file *fp, struct proc *p) { - int error = 0; + struct socket *so; + int error; + + error = 0; + + KASSERT(fp); + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + KASSERT(p); + KASSERT(p->p_inst); + + /* FIXME - instance - cross-check */ + + if (fp->f_cred->cr_inst->i_uuid != p->p_inst->i_uuid) + printf("error: fp->f_cred->cr_inst = %d, " + "p->p_inst = %d\n", + fp->f_cred->cr_inst->i_uuid, + p->p_inst->i_uuid); + + so = (struct socket *) fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + + if (so->so_inst->i_uuid != p->p_inst->i_uuid) + printf("error: so->so_inst = %d, " + "p->p_inst = %d\n", + so->so_inst->i_uuid, + p->p_inst->i_uuid); + if (fp->f_data) - error = soclose((struct socket *)fp->f_data); + error = soclose(so); fp->f_data = 0; return (error); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/syscalls.c mult-netbsd-3.1/sys/kern/syscalls.c --- NetBSD-3.1/sys/kern/syscalls.c 2005-02-27 00:02:40.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/syscalls.c 2007-11-15 13:34:52.000000000 +0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscalls.c,v 1.158 2005/02/27 00:02:40 perry Exp $ */ +/* $NetBSD$ */ /* * System call names. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.158 2005/02/27 00:02:40 perry Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #include "opt_ktrace.h" @@ -26,6 +26,7 @@ #include #include #include +#include #endif /* _KERNEL_OPT */ const char *const syscallnames[] = { @@ -510,4 +511,5 @@ "extattr_list_link", /* 372 = extattr_list_link */ "pselect", /* 373 = pselect */ "pollts", /* 374 = pollts */ + "instctl", /* 375 = instctl */ }; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/syscalls.master mult-netbsd-3.1/sys/kern/syscalls.master --- NetBSD-3.1/sys/kern/syscalls.master 2005-02-25 19:53:56.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/syscalls.master 2007-11-15 13:34:52.000000000 +0000 @@ -54,6 +54,7 @@ #include #include #include +#include %% @@ -751,3 +752,6 @@ const sigset_t *mask); } 374 STD { int sys_pollts(struct pollfd *fds, u_int nfds, \ const struct timespec *ts, const sigset_t *mask); } +375 STD { int sys_instctl(struct instctl *ctl); } + + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/tty.c mult-netbsd-3.1/sys/kern/tty.c --- NetBSD-3.1/sys/kern/tty.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/tty.c 2007-12-09 13:38:53.000000000 +0000 @@ -61,6 +61,7 @@ #include #include #include +#include #include @@ -224,9 +225,11 @@ int ttyopen(struct tty *tp, int dialout, int nonblock) { - int s, error; + int s, error; + struct proc *p; error = 0; + p = curproc; s = spltty(); TTY_LOCK(tp); @@ -815,6 +818,9 @@ int s, error; struct nameidata nd; + KASSERT(NULL != p); + KASSERT(NULL != p->p_inst); + /* If the ioctl involves modification, hang if in the background. */ switch (cmd) { case TIOCFLUSH: @@ -1167,9 +1173,9 @@ return (ENOTTY); if (pgid < 0) - pgrp = pgfind(-pgid); + pgrp = pgfind(p->p_inst, -pgid); else { - struct proc *p1 = pfind(pgid); + struct proc *p1 = pfind(p->p_inst, pgid); if (!p1) return (ESRCH); pgrp = p1->p_pgrp; @@ -1183,7 +1189,7 @@ break; } case TIOCSPGRP: { /* set pgrp of tty */ - struct pgrp *pgrp = pgfind(*(int *)data); + struct pgrp *pgrp = pgfind(p->p_inst, *(int *)data); if (!isctty(p, tp)) return (ENOTTY); diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/tty_ptm.c mult-netbsd-3.1/sys/kern/tty_ptm.c --- NetBSD-3.1/sys/kern/tty_ptm.c 2004-11-30 04:25:44.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/tty_ptm.c 2007-11-27 12:47:33.000000000 +0000 @@ -111,6 +111,7 @@ return pty_makedev('t', i); } + /* * Hacked up version of vn_open. We _only_ handle ptys and only open * them with FREAD|FWRITE and never deal with creat or stuff like that. @@ -129,9 +130,10 @@ } /* - * Get us a fresh cred with root privileges. + * Get us a fresh cred with root privileges. Copy over the + * instance of the caller. */ - cred = crget(); + cred = crdupinst(p->p_ucred); error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); crfree(cred); @@ -145,6 +147,7 @@ return 0; } + static int pty_alloc_master(struct proc *p, int *fd, dev_t *dev) { @@ -193,6 +196,7 @@ FILE_SET_MATURE(fp); FILE_UNUSE(fp, p); return 0; + bad: FILE_UNUSE(fp, p); fdremove(p->p_fd, *fd); @@ -200,6 +204,7 @@ return error; } + int pty_grant_slave(struct proc *p, dev_t dev) { @@ -225,10 +230,14 @@ struct vattr vattr; struct ucred *cred; (*ptm->getvattr)(ptm, p, &vattr); - /* Get a fake cred to pretend we're root. */ - cred = crget(); + /* + * Get a fake cred to pretend we're root. Copy over the + * instance of the caller. + */ + cred = crdupinst(p->p_ucred); error = VOP_SETATTR(vp, &vattr, cred, p); crfree(cred); + if (error) { DPRINTF(("setattr %d\n", error)); VOP_UNLOCK(vp, 0); @@ -248,6 +257,7 @@ return 0; } + static int pty_alloc_slave(struct proc *p, int *fd, dev_t dev) { @@ -286,6 +296,7 @@ return error; } + struct ptm_pty * pty_sethandler(struct ptm_pty *nptm) { @@ -294,6 +305,7 @@ return optm; } + int pty_fill_ptmget(dev_t dev, int cfd, int sfd, void *data) { @@ -313,6 +325,7 @@ return (*ptm->makename)(ptm, ptmg->sn, sizeof(ptmg->sn), dev, 't'); } + void /*ARGSUSED*/ ptmattach(int n) @@ -328,6 +341,7 @@ #endif } + int /*ARGSUSED*/ ptmopen(dev_t dev, int flag, int mode, struct proc *p) @@ -355,6 +369,7 @@ return (0); } + int /*ARGSUSED*/ ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) @@ -389,3 +404,4 @@ return error; } #endif + diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/tty_pty.c mult-netbsd-3.1/sys/kern/tty_pty.c --- NetBSD-3.1/sys/kern/tty_pty.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/tty_pty.c 2007-11-27 12:47:33.000000000 +0000 @@ -60,6 +60,7 @@ #include #include #include +#include #define DEFAULT_NPTYS 16 /* default number of initial ptys */ #define DEFAULT_MAXPTYS 992 /* default maximum number of ptys */ @@ -71,14 +72,18 @@ #define BUFSIZ 100 /* Chunk size iomoved to/from user */ + struct pt_softc { - struct tty *pt_tty; - int pt_flags; - struct selinfo pt_selr, pt_selw; - u_char pt_send; - u_char pt_ucntl; + struct tty *pt_tty; + int pt_flags; + struct selinfo pt_selr; + struct selinfo pt_selw; + u_char pt_send; + u_char pt_ucntl; + uint pt_iuuid; }; + static struct pt_softc **pt_softc = NULL; /* pty array */ static int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */ struct simplelock pt_softc_mutex = SIMPLELOCK_INITIALIZER; @@ -336,8 +341,11 @@ tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); /* would be done in xxparam() */ - } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) + } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) return (EBUSY); + else if (pti->pt_iuuid != p->p_inst->i_uuid) + return (EBUSY); + if (tp->t_oproc) /* Ctrlr still around. */ SET(tp->t_state, TS_CARR_ON); @@ -556,18 +564,16 @@ splx(s); } + /*ARGSUSED*/ int -ptcopen(dev, flag, devtype, p) - dev_t dev; - int flag, devtype; - struct proc *p; +ptcopen(dev_t dev, int flag, int devtype, struct proc *p) { - struct pt_softc *pti; - struct tty *tp; - int error; - int ptn = minor(dev); - int s; + struct pt_softc *pti; + struct tty *tp; + int error, ptn, s; + + ptn = minor(dev); if ((error = pty_check(ptn)) != 0) return (error); @@ -590,6 +596,7 @@ pti->pt_flags = 0; pti->pt_send = 0; pti->pt_ucntl = 0; + pti->pt_iuuid = p->p_inst->i_uuid; return (0); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/tty_tty.c mult-netbsd-3.1/sys/kern/tty_tty.c --- NetBSD-3.1/sys/kern/tty_tty.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/tty_tty.c 2007-12-09 13:38:53.000000000 +0000 @@ -46,6 +46,7 @@ #include #include #include +#include #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/uipc_domain.c mult-netbsd-3.1/sys/kern/uipc_domain.c --- NetBSD-3.1/sys/kern/uipc_domain.c 2005-03-09 05:07:19.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/uipc_domain.c 2007-11-23 10:17:19.000000000 +0000 @@ -50,6 +50,7 @@ #include #include #include +#include void pffasttimo(void *); void pfslowtimo(void *); @@ -248,6 +249,10 @@ size_t len, needed, elem_size, out_size; int error, elem_count, pf, type, pf2; + KASSERT(NULL != l); + KASSERT(NULL != l->l_proc); + KASSERT(NULL != l->l_inst); + if (namelen == 1 && name[0] == CTL_QUERY) return (sysctl_query(SYSCTLFN_CALL(rnode))); @@ -278,7 +283,7 @@ * there's no "list" of local domain sockets, so we have * to walk the file list looking for them. :-/ */ - LIST_FOREACH(fp, &filehead, f_list) { + LIST_FOREACH(fp, &l->l_inst->i_filehead, f_list) { if (fp->f_type != DTYPE_SOCKET) continue; so = (struct socket *)fp->f_data; diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/uipc_socket.c mult-netbsd-3.1/sys/kern/uipc_socket.c --- NetBSD-3.1/sys/kern/uipc_socket.c 2006-10-25 13:58:56.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/uipc_socket.c 2007-12-18 10:59:49.000000000 +0000 @@ -91,14 +91,19 @@ #include #include #include +#include #include -POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL); + +POOL_INIT(socket_pool, sizeof(struct socket), + 0, 0, 0, "sockpl", NULL); + MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options"); MALLOC_DEFINE(M_SONAME, "soname", "socket name"); + extern int somaxconn; /* patchable (XXX sysctl) */ int somaxconn = SOMAXCONN; @@ -129,7 +134,6 @@ void soinit(void) { - /* Set the initial adjusted socket buffer size. */ if (sb_max_set(sb_max)) panic("bad initial sb_max value: %lu\n", sb_max); @@ -163,8 +167,11 @@ static __inline vsize_t sokvareserve(struct socket *so, vsize_t len) { - int s; - int error; + int s; + int error; + + KASSERT(so); + KASSERT(so->so_inst); s = splvm(); simple_lock(&so_pendfree_slock); @@ -200,10 +207,11 @@ return len; } + static __inline void sokvaunreserve(vsize_t len) { - int s; + int s; s = splvm(); simple_lock(&so_pendfree_slock); @@ -214,56 +222,42 @@ splx(s); } + /* * sokvaalloc: allocate kva for loan. */ - vaddr_t sokvaalloc(vsize_t len, struct socket *so) { vaddr_t lva; - /* - * reserve kva. - */ + KASSERT(so); + KASSERT(so->so_inst); if (sokvareserve(so, len) == 0) - return 0; - - /* - * allocate kva. - */ + return(0); lva = uvm_km_valloc_wait(kernel_map, len); if (lva == 0) { sokvaunreserve(len); - return (0); + return(0); } - return lva; + return(lva); } + /* * sokvafree: free kva for loan. */ - void sokvafree(vaddr_t sva, vsize_t len) { - - /* - * free kva. - */ - uvm_km_free(kernel_map, sva, len); - - /* - * unreserve kva. - */ - sokvaunreserve(len); } + static void sodoloanfree(struct vm_page **pgs, caddr_t buf, size_t size) { @@ -293,11 +287,15 @@ sokvafree(sva, len); } + static size_t sodopendfree(struct socket *so) { - int s; - size_t rv; + int s; + size_t rv; + + KASSERT(so); + KASSERT(so->so_inst); s = splvm(); simple_lock(&so_pendfree_slock); @@ -308,19 +306,22 @@ return rv; } + /* - * sodopendfreel: free mbufs on "pendfree" list. - * unlock and relock so_pendfree_slock when freeing mbufs. + * sodopendfreel: free mbufs on "pendfree" list. unlock and relock + * so_pendfree_slock when freeing mbufs. * * => called with so_pendfree_slock held. * => called at splvm. */ - static size_t sodopendfreel(struct socket *so) { size_t rv = 0; + KASSERT(so); + KASSERT(so->so_inst); + LOCK_ASSERT(simple_lock_held(&so_pendfree_slock)); for (;;) { @@ -351,17 +352,16 @@ return (rv); } + void soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg) { int s; if (m == NULL) { - /* * called from MEXTREMOVE. */ - sodoloanfree(NULL, buf, size); return; } @@ -372,7 +372,6 @@ * we can't do it in interrupt context * because we need to put kva back to kernel_map. */ - s = splvm(); simple_lock(&so_pendfree_slock); m->m_next = so_pendfree; @@ -383,6 +382,7 @@ splx(s); } + static long sosend_loan(struct socket *so, struct uio *uio, struct mbuf *m, long space) { @@ -392,6 +392,9 @@ vaddr_t lva, va; int npgs, i, error; + KASSERT(so); + KASSERT(so->so_inst); + if (uio->uio_segflg != UIO_USERSPACE) return (0); @@ -442,12 +445,12 @@ return (space); } + /* - * Socket operation routines. - * These routines are called by the routines in - * sys_socket.c or from a system process, and - * implement the semantics of socket operations by - * switching out to the protocol specific routines. + * Socket operation routines. These routines are called by the routines + * in sys_socket.c or from a system process, and implement the semantics + * of socket operations by switching out to the protocol specific + * routines. */ /*ARGSUSED*/ int @@ -465,6 +468,11 @@ return (EPROTONOSUPPORT); if (prp->pr_type != type) return (EPROTOTYPE); + + /* XXX - at one time, this switched on p being null. */ + KASSERT(p); + KASSERT(p->p_inst); + s = splsoftnet(); so = pool_get(&socket_pool, PR_WAITOK); memset((caddr_t)so, 0, sizeof(*so)); @@ -479,10 +487,12 @@ so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner; so->so_mowner = &prp->pr_domain->dom_mowner; #endif - if (p != 0) - so->so_uid = p->p_ucred->cr_uid; - else - so->so_uid = UID_MAX; + so->so_inst = p->p_inst; + so->so_uid = p->p_ucred->cr_uid; + + inst_hold(so->so_inst); + so->so_inst->i_nsocks++; + error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)(long)proto, (struct mbuf *)0, p); if (error) { @@ -496,11 +506,18 @@ return (0); } + int sobind(struct socket *so, struct mbuf *nam, struct proc *p) { int s, error; + KASSERT(so); + KASSERT(so->so_inst); + KASSERT(p); + + /* FIXME - instances - cross-check p_inst/so_inst? */ + s = splsoftnet(); error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam, (struct mbuf *)0, p); @@ -508,11 +525,15 @@ return (error); } + int solisten(struct socket *so, int backlog) { int s, error; + KASSERT(so); + KASSERT(so->so_inst); + s = splsoftnet(); error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); @@ -529,10 +550,10 @@ return (0); } + void sofree(struct socket *so) { - if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { @@ -544,21 +565,25 @@ if (!soqremque(so, 0)) return; } + if (so->so_rcv.sb_hiwat) - (void)chgsbsize(so->so_uid, &so->so_rcv.sb_hiwat, 0, - RLIM_INFINITY); + (void)chgsbsize(so->so_uid, + &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY); if (so->so_snd.sb_hiwat) - (void)chgsbsize(so->so_uid, &so->so_snd.sb_hiwat, 0, - RLIM_INFINITY); + (void)chgsbsize(so->so_uid, + &so->so_snd.sb_hiwat, 0, RLIM_INFINITY); sbrelease(&so->so_snd, so); sorflush(so); + + so->so_inst->i_nsocks--; + inst_release(so->so_inst); pool_put(&socket_pool, so); } + /* - * Close a socket on last file table reference removal. - * Initiate disconnect if connected. - * Free socket when disconnect complete. + * Close a socket on last file table reference removal. Initiate + * disconnect if connected. Free socket when disconnect complete. */ int soclose(struct socket *so) @@ -566,6 +591,9 @@ struct socket *so2; int s, error; + KASSERT(so); + KASSERT(so->so_inst); + error = 0; s = splsoftnet(); /* conservative */ if (so->so_options & SO_ACCEPTCONN) { @@ -616,13 +644,15 @@ return (error); } + /* * Must be called at splsoftnet... */ int soabort(struct socket *so) { - + KASSERT(so); + KASSERT(so->so_inst); return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0); } @@ -632,6 +662,9 @@ { int s, error; + KASSERT(so); + KASSERT(so->so_inst); + error = 0; s = splsoftnet(); if ((so->so_state & SS_NOFDREF) == 0) @@ -648,11 +681,15 @@ return (error); } + int soconnect(struct socket *so, struct mbuf *nam, struct proc *p) { int s, error; + KASSERT(so); + KASSERT(so->so_inst); + if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); s = splsoftnet(); @@ -663,21 +700,29 @@ * a null address. */ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && - ((so->so_proto->pr_flags & PR_CONNREQUIRED) || - (error = sodisconnect(so)))) + ((so->so_proto->pr_flags & PR_CONNREQUIRED) || + (error = sodisconnect(so)))) error = EISCONN; - else + else { error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, - (struct mbuf *)0, nam, (struct mbuf *)0, p); + (struct mbuf *)0, nam, + (struct mbuf *)0, p); + } splx(s); return (error); } + int soconnect2(struct socket *so1, struct socket *so2) { int s, error; + KASSERT(so1); + KASSERT(so1->so_inst); + KASSERT(so2); + KASSERT(so2->so_inst); + s = splsoftnet(); error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0, @@ -686,11 +731,15 @@ return (error); } + int sodisconnect(struct socket *so) { int s, error; + KASSERT(so); + KASSERT(so->so_inst); + s = splsoftnet(); if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; @@ -709,32 +758,36 @@ return (error); } + #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) /* - * Send on a socket. - * If send must go all at once and message is larger than - * send buffering, then hard error. - * Lock against other senders. - * If must go all at once and not enough room now, then - * inform user that this would block and do nothing. - * Otherwise, if nonblocking, send as much as possible. - * The data to be sent is described by "uio" if nonzero, - * otherwise by the mbuf chain "top" (which must be null - * if uio is not). Data provided in mbuf chain must be small - * enough to send all at once. + * Send on a socket. If send must go all at once and message is larger + * than send buffering, then hard error. Lock against other senders. + * If must go all at once and not enough room now, then inform user that + * this would block and do nothing. Otherwise, if nonblocking, send as + * much as possible. The data to be sent is described by "uio" if + * nonzero, otherwise by the mbuf chain "top" (which must be null if uio + * is not). Data provided in mbuf chain must be small enough to send + * all at once. * - * Returns nonzero on error, timeout or signal; callers - * must check for short counts if EINTR/ERESTART are returned. - * Data and control buffers are freed on return. + * Returns nonzero on error, timeout or signal; callers must check for + * short counts if EINTR/ERESTART are returned. Data and control + * buffers are freed on return. */ int -sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, - struct mbuf *control, int flags, struct proc *p) +sosend(struct socket *so, struct mbuf *addr, struct uio *uio, + struct mbuf *top, struct mbuf *control, + int flags, struct proc *p) { struct mbuf **mp, *m; long space, len, resid, clen, mlen; int error, s, dontroute, atomic; + KASSERT(so); + KASSERT(so->so_inst); + + /* FIXME - instance - cross-check p_inst/so_inst */ + sodopendfree(so); clen = 0; @@ -911,17 +964,17 @@ return (error); } + /* - * Implement receive operations on a socket. - * We depend on the way that records are added to the sockbuf - * by sbappend*. In particular, each record (mbufs linked through m_next) - * must begin with an address if the protocol so specifies, - * followed by an optional mbuf or mbufs containing ancillary data, - * and then zero or more mbufs of data. - * In order to avoid blocking network interrupts for the entire time here, - * we splx() while doing the actual copy to user space. - * Although the sockbuf is locked, new data may still be appended, - * and thus we must maintain consistency of the sockbuf during that time. + * Implement receive operations on a socket. We depend on the way that + * records are added to the sockbuf by sbappend*. In particular, each + * record (mbufs linked through m_next) must begin with an address if + * the protocol so specifies, followed by an optional mbuf or mbufs + * containing ancillary data, and then zero or more mbufs of data. In + * order to avoid blocking network interrupts for the entire time here, + * we splx() while doing the actual copy to user space. Although the + * sockbuf is locked, new data may still be appended, and thus we must + * maintain consistency of the sockbuf during that time. * * The caller may receive the data as a single mbuf chain by supplying * an mbuf **mp0 for use in returning the chain. The uio is then used @@ -929,21 +982,29 @@ */ int soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, - struct mbuf **mp0, struct mbuf **controlp, int *flagsp) + struct mbuf **mp0, struct mbuf **controlp, int *flagsp) { - struct proc * p; + struct proc *p; struct mbuf *m, **mp; int flags, len, error, s, offset, moff, type, orig_resid; const struct protosw *pr; struct mbuf *nextrecord; int mbuf_removed = 0; + KASSERT(so); + KASSERT(so->so_inst); + pr = so->so_proto; mp = mp0; type = 0; orig_resid = uio->uio_resid; p = uio->uio_procp; + KASSERT(p); + KASSERT(p->p_inst); + + /* FIXME - instance - cross check ui->p_inst/so_inst */ + if (paddr) *paddr = 0; if (controlp) @@ -1340,11 +1401,15 @@ return (error); } + int soshutdown(struct socket *so, int how) { const struct protosw *pr; + KASSERT(so); + KASSERT(so->so_inst); + pr = so->so_proto; if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) return (EINVAL); @@ -1357,6 +1422,7 @@ return (0); } + void sorflush(struct socket *so) { @@ -1364,6 +1430,9 @@ const struct protosw *pr; int s; + KASSERT(so); + KASSERT(so->so_inst); + sb = &so->so_rcv; pr = so->so_proto; sb->sb_flags |= SB_NOINTR; @@ -1384,12 +1453,16 @@ sbrelease(&asb, so); } + int sosetopt(struct socket *so, int level, int optname, struct mbuf *m0) { int error; struct mbuf *m; + KASSERT(so); + KASSERT(so->so_inst); + error = 0; m = m0; if (level != SOL_SOCKET) { @@ -1531,11 +1604,15 @@ return (error); } + int sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) { struct mbuf *m; + KASSERT(so); + KASSERT(so->so_inst); + if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) { return ((*so->so_proto->pr_ctloutput) @@ -1618,10 +1695,12 @@ } } + void sohasoutofband(struct socket *so) { - fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); + fownsignal(so->so_inst, so->so_pgid, + SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); selwakeup(&so->so_rcv.sb_sel); } @@ -1631,6 +1710,10 @@ struct socket *so; so = (struct socket *)kn->kn_fp->f_data; + + KASSERT(so); + KASSERT(so->so_inst); + SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist)) so->so_rcv.sb_flags &= ~SB_KNOTE; @@ -1643,6 +1726,10 @@ struct socket *so; so = (struct socket *)kn->kn_fp->f_data; + + KASSERT(so); + KASSERT(so->so_inst); + kn->kn_data = so->so_rcv.sb_cc; if (so->so_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; @@ -1662,6 +1749,10 @@ struct socket *so; so = (struct socket *)kn->kn_fp->f_data; + + KASSERT(so); + KASSERT(so->so_inst); + SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist)) so->so_snd.sb_flags &= ~SB_KNOTE; @@ -1674,6 +1765,10 @@ struct socket *so; so = (struct socket *)kn->kn_fp->f_data; + + KASSERT(so); + KASSERT(so->so_inst); + kn->kn_data = sbspace(&so->so_snd); if (so->so_state & SS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; @@ -1698,6 +1793,9 @@ so = (struct socket *)kn->kn_fp->f_data; + KASSERT(so); + KASSERT(so->so_inst); + /* * Set kn_data to number of incoming connections, not * counting partial (incomplete) connections. @@ -1713,6 +1811,7 @@ static const struct filterops sowrite_filtops = { 1, NULL, filt_sowdetach, filt_sowrite }; + int soo_kqfilter(struct file *fp, struct knote *kn) { @@ -1720,6 +1819,10 @@ struct sockbuf *sb; so = (struct socket *)kn->kn_fp->f_data; + + KASSERT(so); + KASSERT(so->so_inst); + switch (kn->kn_filter) { case EVFILT_READ: if (so->so_options & SO_ACCEPTCONN) @@ -1744,6 +1847,7 @@ static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); + /* * sysctl helper routine for kern.somaxkva. ensures that the given * value is not too small. @@ -1756,6 +1860,8 @@ struct sysctlnode node; int s; + /* FIXME - instance - values should be per-instance */ + new_somaxkva = somaxkva; node = *rnode; node.sysctl_data = &new_somaxkva; @@ -1776,9 +1882,9 @@ return (error); } + SYSCTL_SETUP(sysctl_kern_somaxkva_setup, "sysctl kern.somaxkva setup") { - sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL, diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/uipc_socket2.c mult-netbsd-3.1/sys/kern/uipc_socket2.c --- NetBSD-3.1/sys/kern/uipc_socket2.c 2005-02-26 21:34:55.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/uipc_socket2.c 2007-11-23 10:17:19.000000000 +0000 @@ -49,6 +49,7 @@ #include #include #include +#include /* * Primitive routines for operating on sockets and socket buffers @@ -60,6 +61,7 @@ const char netio[] = "netio"; const char netlck[] = "netlck"; +/* FIXME - instance appropriation? */ u_long sb_max = SB_MAX; /* maximum socket buffer size */ static u_long sb_max_adj; /* adjusted sb_max */ @@ -96,7 +98,6 @@ void soisconnecting(struct socket *so) { - so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTING; } @@ -159,6 +160,9 @@ struct socket *so; int soqueue; + KASSERT(head); + KASSERT(head->so_inst); + soqueue = connstatus ? 1 : 0; if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) return ((struct socket *)0); @@ -176,17 +180,24 @@ so->so_send = head->so_send; so->so_receive = head->so_receive; so->so_uid = head->so_uid; + so->so_inst = head->so_inst; #ifdef MBUFTRACE so->so_mowner = head->so_mowner; so->so_rcv.sb_mowner = head->so_rcv.sb_mowner; so->so_snd.sb_mowner = head->so_snd.sb_mowner; #endif + + inst_hold(so->so_inst); + so->so_inst->i_nsocks++; + (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); soqinsque(head, so, soqueue); if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0, (struct proc *)0)) { (void) soqremque(so, soqueue); + so->so_inst->i_nsocks--; + inst_release(so->so_inst); pool_put(&socket_pool, so); return (NULL); } @@ -307,6 +318,9 @@ void sowakeup(struct socket *so, struct sockbuf *sb, int code) { + KASSERT(so); + KASSERT(so->so_inst); + selnotify(&sb->sb_sel, 0); sb->sb_flags &= ~SB_SEL; if (sb->sb_flags & SB_WAIT) { @@ -319,7 +333,9 @@ band = POLLIN|POLLRDNORM; else band = POLLOUT|POLLWRNORM; - fownsignal(so->so_pgid, SIGIO, code, band, so); + + fownsignal(so->so_inst, so->so_pgid, + SIGIO, code, band, so); } if (sb->sb_flags & SB_UPCALL) (*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT); @@ -402,23 +418,28 @@ int sbreserve(struct sockbuf *sb, u_long cc, struct socket *so) { - struct proc *p = curproc; /* XXX */ - rlim_t maxcc; - uid_t uid; + struct proc *p = curproc; /* XXX */ + rlim_t maxcc; + uid_t uid; + + /* FIXME - instance - cross-check so_inst/p_inst */ KDASSERT(sb_max_adj != 0); if (cc == 0 || cc > sb_max_adj) return (0); if (so) { - if (p && p->p_ucred->cr_uid == so->so_uid) + KASSERT(so->so_inst); + if (p && p->p_ucred->cr_uid == so->so_uid) { + KASSERT(p->p_inst); maxcc = p->p_rlimit[RLIMIT_SBSIZE].rlim_cur; - else + } else maxcc = RLIM_INFINITY; uid = so->so_uid; } else { uid = 0; /* XXX: nothing better */ maxcc = RLIM_INFINITY; } + if (!chgsbsize(uid, &sb->sb_hiwat, cc, maxcc)) return 0; sb->sb_mbmax = min(cc * 2, sb_max); @@ -433,10 +454,8 @@ void sbrelease(struct sockbuf *sb, struct socket *so) { - sbflush(sb); - (void)chgsbsize(so->so_uid, &sb->sb_hiwat, 0, - RLIM_INFINITY); + (void)chgsbsize(so->so_uid, &sb->sb_hiwat, 0, RLIM_INFINITY); sb->sb_mbmax = 0; } diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/uipc_syscalls.c mult-netbsd-3.1/sys/kern/uipc_syscalls.c --- NetBSD-3.1/sys/kern/uipc_syscalls.c 2006-10-24 17:59:08.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/uipc_syscalls.c 2007-11-19 14:26:40.000000000 +0000 @@ -282,11 +282,18 @@ /* getsock() will use the descriptor for us */ if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); + + KASSERT(fp->f_cred); + KASSERT(fp->f_cred->cr_inst); + so = (struct socket *)fp->f_data; if (so->so_state & SS_ISCONNECTING) { error = EALREADY; goto out; } + + KASSERT(so->so_inst); + error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); if (error) diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/uipc_usrreq.c mult-netbsd-3.1/sys/kern/uipc_usrreq.c --- NetBSD-3.1/sys/kern/uipc_usrreq.c 2006-09-08 11:38:10.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/uipc_usrreq.c 2007-11-23 10:17:20.000000000 +0000 @@ -120,6 +120,7 @@ #include #include #include +#include /* * Unix communications domain. @@ -200,6 +201,13 @@ u_int newhiwat; int error = 0; + KASSERT(so); + KASSERT(so->so_inst); + + /* + * XXX - instance - struct ps can be NULL (see uipc_socket.c). + */ + if (req == PRU_CONTROL) return (EOPNOTSUPP); @@ -285,7 +293,7 @@ unp->unp_mbcnt = rcv->sb_mbcnt; newhiwat = snd->sb_hiwat + unp->unp_cc - rcv->sb_cc; (void)chgsbsize(so2->so_uid, - &snd->sb_hiwat, newhiwat, RLIM_INFINITY); + &snd->sb_hiwat, newhiwat, RLIM_INFINITY); unp->unp_cc = rcv->sb_cc; sowwakeup(so2); #undef snd @@ -1110,27 +1118,33 @@ void unp_gc(void) { - struct file *fp, *nextfp; - struct socket *so, *so1; - struct file **extra_ref, **fpp; - int nunref, i; + struct file *fp, *nextfp; + struct socket *so, *so1; + struct file **extra_ref, **fpp; + struct inst *inst; + int nunref, i; if (unp_gcing) return; + unp_gcing = 1; unp_defer = 0; /* Clear mark bits */ - LIST_FOREACH(fp, &filehead, f_list) - fp->f_flag &= ~(FMARK|FDEFER); + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) + LIST_FOREACH(fp, &inst->i_filehead, f_list) + fp->f_flag &= ~(FMARK|FDEFER); + instlist_unlock_read(); /* * Iterate over the set of descriptors, marking ones believed * (based on refcount) to be referenced from a process, and * marking for rescan descriptors which are queued on a socket. */ - do { - LIST_FOREACH(fp, &filehead, f_list) { + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) do { + LIST_FOREACH(fp, &inst->i_filehead, f_list) { if (fp->f_flag & FDEFER) { fp->f_flag &= ~FDEFER; unp_defer--; @@ -1185,6 +1199,8 @@ } } while (unp_defer); + instlist_unlock_read(); + /* * Sweep pass. Find unmarked descriptors, and free them. * @@ -1227,37 +1243,46 @@ * * 91/09/19, bsy@cs.cmu.edu */ - extra_ref = malloc(nfiles * sizeof(struct file *), M_FILE, M_WAITOK); - for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref; fp != 0; - fp = nextfp) { - nextfp = LIST_NEXT(fp, f_list); - simple_lock(&fp->f_slock); - if (fp->f_count != 0 && - fp->f_count == fp->f_msgcount && !(fp->f_flag & FMARK)) { - *fpp++ = fp; - nunref++; - fp->f_count++; + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) { + extra_ref = malloc(inst->i_nfiles * + sizeof(struct file *), M_FILE, M_WAITOK); + for (nunref = 0, fp = LIST_FIRST + (&inst->i_filehead), + fpp = extra_ref; fp != 0; + fp = nextfp) { + nextfp = LIST_NEXT(fp, f_list); + simple_lock(&fp->f_slock); + if (fp->f_count != 0 && fp->f_count == + fp->f_msgcount && + !(fp->f_flag & FMARK)) { + *fpp++ = fp; + nunref++; + fp->f_count++; + } + simple_unlock(&fp->f_slock); } - simple_unlock(&fp->f_slock); - } - for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { - fp = *fpp; - simple_lock(&fp->f_slock); - FILE_USE(fp); - if (fp->f_type == DTYPE_SOCKET) - sorflush((struct socket *)fp->f_data); - FILE_UNUSE(fp, NULL); - } - for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { - fp = *fpp; - simple_lock(&fp->f_slock); - FILE_USE(fp); - (void) closef(fp, (struct proc *)0); + for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { + fp = *fpp; + simple_lock(&fp->f_slock); + FILE_USE(fp); + if (fp->f_type == DTYPE_SOCKET) + sorflush((struct socket *)fp->f_data); + FILE_UNUSE(fp, NULL); + } + for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { + fp = *fpp; + simple_lock(&fp->f_slock); + FILE_USE(fp); + (void) closef(fp, (struct proc *)0); + } + free((caddr_t)extra_ref, M_FILE); } - free((caddr_t)extra_ref, M_FILE); + instlist_unlock_read(); unp_gcing = 0; } + void unp_dispose(struct mbuf *m) { diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/vfs_lookup.c mult-netbsd-3.1/sys/kern/vfs_lookup.c --- NetBSD-3.1/sys/kern/vfs_lookup.c 2006-01-20 20:48:41.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/vfs_lookup.c 2007-11-09 18:08:21.000000000 +0000 @@ -40,7 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.57.2.3 2006/01/20 20:48:41 riz Exp $"); #include "opt_ktrace.h" -#include "opt_systrace.h" #include #include @@ -59,9 +58,6 @@ #ifdef KTRACE #include #endif -#ifdef SYSTRACE -#include -#endif struct pool pnbuf_pool; /* pathname buffer pool */ struct pool_cache pnbuf_cache; /* pathname buffer cache */ @@ -140,10 +136,6 @@ if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) ktrnamei(cnp->cn_proc, cnp->cn_pnbuf); #endif -#ifdef SYSTRACE - if (ISSET(cnp->cn_proc->p_flag, P_SYSTRACE)) - systrace_namei(ndp); -#endif /* * Get starting point for the translation. diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/vfs_subr.c mult-netbsd-3.1/sys/kern/vfs_subr.c --- NetBSD-3.1/sys/kern/vfs_subr.c 2006-09-02 21:48:57.000000000 +0100 +++ mult-netbsd-3.1/sys/kern/vfs_subr.c 2007-11-11 13:27:02.000000000 +0000 @@ -2379,10 +2379,13 @@ np->netc_anon.cr_ref = 1; return 0; check: + /* FIXME - instances */ +#if 0 if (enp->netc_exflags != argp->ex_flags || crcmp(&enp->netc_anon, &argp->ex_anon) != 0) error = EPERM; else +#endif error = 0; out: free(np, M_NETADDR); diff -r -u -N --exclude CVS NetBSD-3.1/sys/kern/vfs_syscalls.c mult-netbsd-3.1/sys/kern/vfs_syscalls.c --- NetBSD-3.1/sys/kern/vfs_syscalls.c 2006-01-20 20:48:41.000000000 +0000 +++ mult-netbsd-3.1/sys/kern/vfs_syscalls.c 2007-11-23 10:17:20.000000000 +0000 @@ -62,6 +62,7 @@ #include #include #include +#include #ifdef KTRACE #include #endif @@ -414,8 +415,10 @@ return; if (VFS_ROOT(olddp->v_mountedhere, &newdp)) panic("mount: lost mount"); - proclist_lock_read(); - PROCLIST_FOREACH(p, &allproc) { + /* FIXME - instance */ + KASSERT(NULL != proc0.p_inst); + proclist_lock_read(proc0.p_inst); + PROCLIST_FOREACH(p, &proc0.p_inst->i_allproc) { cwdi = p->p_cwdi; if (!cwdi) continue; @@ -430,7 +433,7 @@ cwdi->cwdi_rdir = newdp; } } - proclist_unlock_read(); + proclist_unlock_read(proc0.p_inst); if (rootvnode == olddp) { vrele(rootvnode); VREF(newdp); diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/Makefile mult-netbsd-3.1/sys/miscfs/Makefile --- NetBSD-3.1/sys/miscfs/Makefile 2004-11-11 18:57:21.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/Makefile 2007-11-10 19:27:11.000000000 +0000 @@ -1,7 +1,7 @@ # $NetBSD: Makefile,v 1.7 2004/11/11 18:57:21 jdolecek Exp $ -SUBDIR= fdesc fifofs genfs kernfs nullfs overlay portal -SUBDIR+= procfs specfs syncfs umapfs +SUBDIR= fdesc fifofs genfs nullfs overlay portal +SUBDIR+= specfs syncfs umapfs INCSDIR= /usr/include/miscfs diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/Makefile mult-netbsd-3.1/sys/miscfs/kernfs/Makefile --- NetBSD-3.1/sys/miscfs/kernfs/Makefile 1998-06-13 00:23:02.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/kernfs/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# $NetBSD: Makefile,v 1.1 1998/06/12 23:23:02 cgd Exp $ - -INCSDIR= /usr/include/miscfs/kernfs - -INCS= kernfs.h - -.include diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/files.kernfs mult-netbsd-3.1/sys/miscfs/kernfs/files.kernfs --- NetBSD-3.1/sys/miscfs/kernfs/files.kernfs 2003-09-08 07:51:53.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/kernfs/files.kernfs 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# $NetBSD: files.kernfs,v 1.2 2003/09/08 06:51:53 itojun Exp $ - -deffs fs_kernfs.h KERNFS # XXX - -file miscfs/kernfs/kernfs_subr.c kernfs -file miscfs/kernfs/kernfs_vfsops.c kernfs -file miscfs/kernfs/kernfs_vnops.c kernfs diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/kernfs.h mult-netbsd-3.1/sys/miscfs/kernfs/kernfs.h --- NetBSD-3.1/sys/miscfs/kernfs/kernfs.h 2005-05-28 13:39:14.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/kernfs/kernfs.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,198 +0,0 @@ -/* $NetBSD: kernfs.h,v 1.23.10.1 2005/05/28 12:39:14 tron Exp $ */ - -/* - * 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. 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. - * - * @(#)kernfs.h 8.6 (Berkeley) 3/29/95 - */ - -#define _PATH_KERNFS "/kern" /* Default mountpoint */ - -#ifdef _KERNEL -#include - -/* - * The different types of node in a kernfs filesystem - */ -typedef enum { - KFSkern, /* the filesystem itself (.) */ - KFSroot, /* the filesystem root (..) */ - KFSnull, /* none aplicable */ - KFStime, /* boottime */ - KFSint, /* integer */ - KFSstring, /* string */ - KFShostname, /* hostname */ - KFSavenrun, /* loadavg */ - KFSdevice, /* device file (rootdev/rrootdev) */ - KFSmsgbuf, /* msgbuf */ - KFSipsecsadir, /* ipsec security association (top dir) */ - KFSipsecspdir, /* ipsec security policy (top dir) */ - KFSipsecsa, /* ipsec security association entry */ - KFSipsecsp, /* ipsec security policy entry */ - KFSsubdir, /* directory */ - KFSlasttype, /* last used type */ - KFSmaxtype = (1<<6) - 1 /* last possible type */ -} kfstype; - -/* - * Control data for the kern file system. - */ -struct kern_target { - u_char kt_type; - u_char kt_namlen; - const char *kt_name; - void *kt_data; - kfstype kt_tag; - u_char kt_vtype; - mode_t kt_mode; -}; - -struct dyn_kern_target { - struct kern_target dkt_kt; - SIMPLEQ_ENTRY(dyn_kern_target) dkt_queue; -}; - -struct kernfs_subdir { - SIMPLEQ_HEAD(,dyn_kern_target) ks_entries; - unsigned int ks_nentries; - unsigned int ks_dirs; - const struct kern_target *ks_parent; -}; - -struct kernfs_node { - LIST_ENTRY(kernfs_node) kfs_hash; /* hash chain */ - TAILQ_ENTRY(kernfs_node) kfs_list; /* flat list */ - struct vnode *kfs_vnode; /* vnode associated with this pfsnode */ - kfstype kfs_type; /* type of procfs node */ - mode_t kfs_mode; /* mode bits for stat() */ - long kfs_fileno; /* unique file id */ - u_int32_t kfs_value; /* SA id or SP id (KFSint) */ - const struct kern_target *kfs_kt; - void *kfs_v; /* pointer to secasvar/secpolicy/mbuf */ - long kfs_cookie; /* fileno cookie */ -}; - -struct kernfs_mount { - TAILQ_HEAD(, kernfs_node) nodelist; - long fileno_cookie; -}; - -#define UIO_MX 32 - -#define KERNFS_FILENO(kt, typ, cookie) \ - ((kt >= &kern_targets[0] && kt < &kern_targets[static_nkern_targets]) \ - ? 2 + ((kt) - &kern_targets[0]) \ - : (((cookie + 1) << 6) | (typ))) -#define KERNFS_TYPE_FILENO(typ, cookie) \ - (((cookie + 1) << 6) | (typ)) - -#define VFSTOKERNFS(mp) ((struct kernfs_mount *)((mp)->mnt_data)) -#define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data) -#define KERNFSTOV(kfs) ((kfs)->kfs_vnode) - -extern const struct kern_target kern_targets[]; -extern int nkern_targets; -extern const int static_nkern_targets; -extern int (**kernfs_vnodeop_p) __P((void *)); -extern struct vfsops kernfs_vfsops; -extern dev_t rrootdev; - -struct secasvar; -struct secpolicy; - -int kernfs_root __P((struct mount *, struct vnode **)); - -void kernfs_hashinit __P((void)); -void kernfs_hashreinit __P((void)); -void kernfs_hashdone __P((void)); -int kernfs_freevp __P((struct vnode *)); -int kernfs_allocvp __P((struct mount *, struct vnode **, kfstype, - const struct kern_target *, u_int32_t)); - -void kernfs_revoke_sa __P((struct secasvar *)); -void kernfs_revoke_sp __P((struct secpolicy *)); - -/* - * Data types for the kernfs file operations. - */ -typedef enum { - KERNFS_XWRITE, - KERNFS_FILEOP_CLOSE, - KERNFS_FILEOP_GETATTR, - KERNFS_FILEOP_IOCTL, - KERNFS_FILEOP_OPEN, - KERNFS_FILEOP_WRITE, -} kfsfileop; - -struct kernfs_fileop { - kfstype kf_type; - kfsfileop kf_fileop; - union { - void *_kf_genop; - int (*_kf_vop)(void *); - int (*_kf_xwrite) - (const struct kernfs_node *, char *, size_t); - } _kf_opfn; - SPLAY_ENTRY(kernfs_fileop) kf_node; -}; -#define kf_genop _kf_opfn -#define kf_vop _kf_opfn._kf_vop -#define kf_xwrite _kf_opfn._kf_xwrite - -typedef struct kern_target kernfs_parentdir_t; -typedef struct dyn_kern_target kernfs_entry_t; - -/* - * Functions for adding kernfs datatypes and nodes. - */ -kfstype kernfs_alloctype(int, const struct kernfs_fileop *); -#define KERNFS_ALLOCTYPE(kf) kernfs_alloctype(sizeof((kf)) / \ - sizeof((kf)[0]), (kf)) -#define KERNFS_ALLOCENTRY(dkt, m_type, m_flags) \ - dkt = (struct dyn_kern_target *)malloc( \ - sizeof(struct dyn_kern_target), (m_type), (m_flags)) -#define KERNFS_INITENTRY(dkt, type, name, data, tag, vtype, mode) do { \ - (dkt)->dkt_kt.kt_type = (type); \ - (dkt)->dkt_kt.kt_namlen = strlen((name)); \ - (dkt)->dkt_kt.kt_name = (name); \ - (dkt)->dkt_kt.kt_data = (data); \ - (dkt)->dkt_kt.kt_tag = (tag); \ - (dkt)->dkt_kt.kt_vtype = (vtype); \ - (dkt)->dkt_kt.kt_mode = (mode); \ -} while (/*CONSTCOND*/0) -#define KERNFS_ENTOPARENTDIR(dkt) &(dkt)->dkt_kt -int kernfs_addentry __P((kernfs_parentdir_t *, kernfs_entry_t *)); - -#ifdef SYSCTL_SETUP_PROTO -SYSCTL_SETUP_PROTO(sysctl_vfs_kernfs_setup); -#endif /* SYSCTL_SETUP_PROTO */ - -#endif /* _KERNEL */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/kernfs_subr.c mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_subr.c --- NetBSD-3.1/sys/miscfs/kernfs/kernfs_subr.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_subr.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,407 +0,0 @@ -/* $NetBSD: kernfs_subr.c,v 1.7 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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. - * - * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95 - */ - -/* - * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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. - * - * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: kernfs_subr.c,v 1.7 2005/02/26 22:59:00 perry Exp $"); - -#ifdef _KERNEL_OPT -#include "opt_ipsec.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef IPSEC -#include -#include -#include -#include -#include -#include -#endif - -void kernfs_hashins __P((struct kernfs_node *)); -void kernfs_hashrem __P((struct kernfs_node *)); -struct vnode *kernfs_hashget __P((kfstype, struct mount *, - const struct kern_target *, u_int32_t)); - -static LIST_HEAD(kfs_hashhead, kernfs_node) *kfs_hashtbl; -static u_long kfs_ihash; /* size of hash table - 1 */ -#define KFSVALUEHASH(v) ((v) & kfs_ihash) - -static struct lock kfs_hashlock; -static struct simplelock kfs_hash_slock; - -#define ISSET(t, f) ((t) & (f)) - -/* - * allocate a kfsnode/vnode pair. the vnode is - * referenced, and locked. - * - * the kfs_type, kfs_value and mount point uniquely - * identify a kfsnode. the mount point is needed - * because someone might mount this filesystem - * twice. - * - * all kfsnodes 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 -kernfs_allocvp(mp, vpp, kfs_type, kt, value) - struct mount *mp; - struct vnode **vpp; - kfstype kfs_type; - const struct kern_target *kt; - u_int32_t value; -{ - struct kernfs_node *kfs = NULL, *kfsp; - struct vnode *vp = NULL; - int error; - long *cookie; - - do { - if ((*vpp = kernfs_hashget(kfs_type, mp, kt, value)) != NULL) - return (0); - } while (lockmgr(&kfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0)); - - if (kfs_type == KFSdevice) { - /* /kern/rootdev = look for device and obey */ - /* /kern/rrootdev = look for device and obey */ - dev_t *dp; - struct vnode *fvp; - -#ifdef DIAGNOSTIC - if (!kt) - panic("kernfs: kt == NULL for KFSdevice"); -#endif - dp = kt->kt_data; - loop: - if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) { - lockmgr(&kfs_hashlock, LK_RELEASE, NULL); - return (ENOENT); - } - vp = fvp; - if (vget(fvp, LK_EXCLUSIVE)) - goto loop; - *vpp = vp; - lockmgr(&kfs_hashlock, LK_RELEASE, NULL); - return (0); - } - - if ((error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &vp)) != 0) { - *vpp = NULL; - lockmgr(&kfs_hashlock, LK_RELEASE, NULL); - return (error); - } - - MALLOC(kfs, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK); - memset(kfs, 0, sizeof(*kfs)); - vp->v_data = kfs; - cookie = &(VFSTOKERNFS(mp)->fileno_cookie); -again: - TAILQ_FOREACH(kfsp, &VFSTOKERNFS(mp)->nodelist, kfs_list) { - if (kfsp->kfs_cookie == *cookie) { - (*cookie) ++; - goto again; - } - if (TAILQ_NEXT(kfsp, kfs_list)) { - if (kfsp->kfs_cookie < *cookie && - *cookie < TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) - break; - if (kfsp->kfs_cookie + 1 < - TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) { - *cookie = kfsp->kfs_cookie + 1; - break; - } - } - } - - kfs->kfs_cookie = *cookie; - - if (kfsp) - TAILQ_INSERT_AFTER(&VFSTOKERNFS(mp)->nodelist, kfsp, kfs, - kfs_list); - else - TAILQ_INSERT_TAIL(&VFSTOKERNFS(mp)->nodelist, kfs, kfs_list); - - kfs->kfs_type = kfs_type; - kfs->kfs_vnode = vp; - kfs->kfs_fileno = KERNFS_FILENO(kt, kfs_type, kfs->kfs_cookie); - kfs->kfs_value = value; - kfs->kfs_kt = kt; - kfs->kfs_mode = kt->kt_mode; - vp->v_type = kt->kt_vtype; - - if (kfs_type == KFSkern) - vp->v_flag = VROOT; - - kernfs_hashins(kfs); - uvm_vnp_setsize(vp, 0); - lockmgr(&kfs_hashlock, LK_RELEASE, NULL); - - *vpp = vp; - return (0); -} - -int -kernfs_freevp(vp) - struct vnode *vp; -{ - struct kernfs_node *kfs = VTOKERN(vp); - - kernfs_hashrem(kfs); - TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list); - - FREE(vp->v_data, M_TEMP); - vp->v_data = 0; - return (0); -} - -/* - * Initialize kfsnode hash table. - */ -void -kernfs_hashinit() -{ - - lockinit(&kfs_hashlock, PINOD, "kfs_hashlock", 0, 0); - kfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, - M_WAITOK, &kfs_ihash); - simple_lock_init(&kfs_hash_slock); -} - -void -kernfs_hashreinit() -{ - struct kernfs_node *pp; - struct kfs_hashhead *oldhash, *hash; - u_long i, oldmask, mask, val; - - hash = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, M_WAITOK, - &mask); - - simple_lock(&kfs_hash_slock); - oldhash = kfs_hashtbl; - oldmask = kfs_ihash; - kfs_hashtbl = hash; - kfs_ihash = mask; - for (i = 0; i <= oldmask; i++) { - while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { - LIST_REMOVE(pp, kfs_hash); - val = KFSVALUEHASH(pp->kfs_value); - LIST_INSERT_HEAD(&hash[val], pp, kfs_hash); - } - } - simple_unlock(&kfs_hash_slock); - hashdone(oldhash, M_UFSMNT); -} - -/* - * Free kfsnode hash table. - */ -void -kernfs_hashdone() -{ - - hashdone(kfs_hashtbl, M_UFSMNT); -} - -struct vnode * -kernfs_hashget(type, mp, kt, value) - kfstype type; - struct mount *mp; - const struct kern_target *kt; - u_int32_t value; -{ - struct kfs_hashhead *ppp; - struct kernfs_node *pp; - struct vnode *vp; - -loop: - simple_lock(&kfs_hash_slock); - ppp = &kfs_hashtbl[KFSVALUEHASH(value)]; - LIST_FOREACH(pp, ppp, kfs_hash) { - vp = KERNFSTOV(pp); - if (pp->kfs_type == type && vp->v_mount == mp && - pp->kfs_kt == kt && pp->kfs_value == value) { - simple_lock(&vp->v_interlock); - simple_unlock(&kfs_hash_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) - goto loop; - return (vp); - } - } - simple_unlock(&kfs_hash_slock); - return (NULL); -} - -/* - * Insert the kfsnode into the hash table and lock it. - */ -void -kernfs_hashins(pp) - struct kernfs_node *pp; -{ - struct kfs_hashhead *ppp; - - /* lock the kfsnode, then put it on the appropriate hash list */ - lockmgr(&pp->kfs_vnode->v_lock, LK_EXCLUSIVE, (struct simplelock *)0); - - simple_lock(&kfs_hash_slock); - ppp = &kfs_hashtbl[KFSVALUEHASH(pp->kfs_value)]; - LIST_INSERT_HEAD(ppp, pp, kfs_hash); - simple_unlock(&kfs_hash_slock); -} - -/* - * Remove the kfsnode from the hash table. - */ -void -kernfs_hashrem(pp) - struct kernfs_node *pp; -{ - simple_lock(&kfs_hash_slock); - LIST_REMOVE(pp, kfs_hash); - simple_unlock(&kfs_hash_slock); -} - -#ifdef IPSEC -void -kernfs_revoke_sa(sav) - struct secasvar *sav; -{ - struct kernfs_node *kfs, *pnext; - struct vnode *vp; - struct kfs_hashhead *ppp; - struct mbuf *m; - - ppp = &kfs_hashtbl[KFSVALUEHASH(ntohl(sav->spi))]; - for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) { - vp = KERNFSTOV(kfs); - pnext = LIST_NEXT(kfs, kfs_hash); - if (vp->v_usecount > 0 && kfs->kfs_type == KFSipsecsa && - kfs->kfs_value == ntohl(sav->spi)) { - m = key_setdumpsa_spi(sav->spi); - if (!m) - VOP_REVOKE(vp, REVOKEALL); - else - m_freem(m); - break; - } - } -} - -void -kernfs_revoke_sp(sp) - struct secpolicy *sp; -{ - struct kernfs_node *kfs, *pnext; - struct vnode *vp; - struct kfs_hashhead *ppp; - - ppp = &kfs_hashtbl[KFSVALUEHASH(sp->id)]; - for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) { - vp = KERNFSTOV(kfs); - pnext = LIST_NEXT(kfs, kfs_hash); - if (vp->v_usecount > 0 && kfs->kfs_type == KFSipsecsa && - kfs->kfs_value == sp->id) - VOP_REVOKE(vp, REVOKEALL); - } -} -#endif diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/kernfs_vfsops.c mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_vfsops.c --- NetBSD-3.1/sys/miscfs/kernfs/kernfs_vfsops.c 2005-01-02 16:08:29.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_vfsops.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,361 +0,0 @@ -/* $NetBSD: kernfs_vfsops.c,v 1.66 2005/01/02 16:08:29 thorpej Exp $ */ - -/* - * 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. 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. - * - * @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95 - */ - -/* - * Kernel params Filesystem - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.66 2005/01/02 16:08:29 thorpej Exp $"); - -#ifdef _KERNEL_OPT -#include "opt_compat_netbsd.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -MALLOC_DEFINE(M_KERNFSMNT, "kernfs mount", "kernfs mount structures"); - -dev_t rrootdev = NODEV; - -void kernfs_init __P((void)); -void kernfs_reinit __P((void)); -void kernfs_done __P((void)); -void kernfs_get_rrootdev __P((void)); -int kernfs_mount __P((struct mount *, const char *, void *, - struct nameidata *, struct proc *)); -int kernfs_start __P((struct mount *, int, struct proc *)); -int kernfs_unmount __P((struct mount *, int, struct proc *)); -int kernfs_statvfs __P((struct mount *, struct statvfs *, struct proc *)); -int kernfs_quotactl __P((struct mount *, int, uid_t, void *, - struct proc *)); -int kernfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); -int kernfs_vget __P((struct mount *, ino_t, struct vnode **)); -int kernfs_fhtovp __P((struct mount *, struct fid *, struct vnode **)); -int kernfs_checkexp __P((struct mount *, struct mbuf *, int *, - struct ucred **)); -int kernfs_vptofh __P((struct vnode *, struct fid *)); - -void -kernfs_init() -{ -#ifdef _LKM - malloc_type_attach(M_KERNFSMNT); -#endif - kernfs_hashinit(); -} - -void -kernfs_reinit() -{ - kernfs_hashreinit(); -} - -void -kernfs_done() -{ -#ifdef _LKM - malloc_type_detach(M_KERNFSMNT); -#endif - kernfs_hashdone(); -} - -void -kernfs_get_rrootdev() -{ - static int tried = 0; - - if (tried) { - /* Already did it once. */ - return; - } - tried = 1; - - if (rootdev == NODEV) - return; - rrootdev = devsw_blk2chr(rootdev); - if (rrootdev != NODEV) - return; - rrootdev = NODEV; - printf("kernfs_get_rrootdev: no raw root device\n"); -} - -/* - * Mount the Kernel params filesystem - */ -int -kernfs_mount(mp, path, data, ndp, p) - struct mount *mp; - const char *path; - void *data; - struct nameidata *ndp; - struct proc *p; -{ - int error = 0; - struct kernfs_mount *fmp; - - if (UIO_MX & (UIO_MX - 1)) { - log(LOG_ERR, "kernfs: invalid directory entry size"); - return (EINVAL); - } - - if (mp->mnt_flag & MNT_GETARGS) - return 0; - /* - * Update is a no-op - */ - if (mp->mnt_flag & MNT_UPDATE) - return (EOPNOTSUPP); - - MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), - M_KERNFSMNT, M_WAITOK); - memset(fmp, 0, sizeof(*fmp)); - TAILQ_INIT(&fmp->nodelist); - - mp->mnt_stat.f_namemax = MAXNAMLEN; - mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = fmp; - vfs_getnewfsid(mp); - - if ((error = set_statvfs_info(path, UIO_USERSPACE, "kernfs", - UIO_SYSSPACE, mp, p)) != 0) { - free(fmp, M_KERNFSMNT); - return error; - } - - kernfs_get_rrootdev(); - return 0; -} - -int -kernfs_start(mp, flags, p) - struct mount *mp; - int flags; - struct proc *p; -{ - - return (0); -} - -int -kernfs_unmount(mp, mntflags, p) - struct mount *mp; - int mntflags; - struct proc *p; -{ - int error; - int flags = 0; - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - if ((error = vflush(mp, 0, flags)) != 0) - return (error); - - /* - * Finally, throw away the kernfs_mount structure - */ - free(mp->mnt_data, M_KERNFSMNT); - mp->mnt_data = NULL; - return (0); -} - -int -kernfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - - /* setup "." */ - return (kernfs_allocvp(mp, vpp, KFSkern, &kern_targets[0], 0)); -} - -int -kernfs_quotactl(mp, cmd, uid, arg, p) - struct mount *mp; - int cmd; - uid_t uid; - void *arg; - struct proc *p; -{ - - return (EOPNOTSUPP); -} - -int -kernfs_statvfs(mp, sbp, p) - struct mount *mp; - struct statvfs *sbp; - struct proc *p; -{ - - sbp->f_bsize = DEV_BSIZE; - sbp->f_frsize = 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_bresvd = 0; - sbp->f_files = 1024; /* XXX lie */ - sbp->f_ffree = 128; /* XXX lie */ - sbp->f_favail = 128; /* XXX lie */ - sbp->f_fresvd = 0; - copy_statvfs_info(sbp, mp); - return (0); -} - -/*ARGSUSED*/ -int -kernfs_sync(mp, waitfor, uc, p) - struct mount *mp; - int waitfor; - struct ucred *uc; - struct proc *p; -{ - - return (0); -} - -/* - * Kernfs flat namespace lookup. - * Currently unsupported. - */ -int -kernfs_vget(mp, ino, vpp) - struct mount *mp; - ino_t ino; - struct vnode **vpp; -{ - - return (EOPNOTSUPP); -} - -/*ARGSUSED*/ -int -kernfs_fhtovp(mp, fhp, vpp) - struct mount *mp; - struct fid *fhp; - struct vnode **vpp; -{ - - return (EOPNOTSUPP); -} - -/*ARGSUSED*/ -int -kernfs_checkexp(mp, mb, what, anon) - struct mount *mp; - struct mbuf *mb; - int *what; - struct ucred **anon; -{ - - return (EOPNOTSUPP); -} - -/*ARGSUSED*/ -int -kernfs_vptofh(vp, fhp) - struct vnode *vp; - struct fid *fhp; -{ - - return (EOPNOTSUPP); -} - -SYSCTL_SETUP(sysctl_vfs_kernfs_setup, "sysctl vfs.kern subtree setup") -{ - - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "vfs", NULL, - NULL, 0, NULL, 0, - CTL_VFS, CTL_EOL); - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "kernfs", - SYSCTL_DESCR("/kern file system"), - NULL, 0, NULL, 0, - CTL_VFS, 11, CTL_EOL); - /* - * XXX the "11" above could be dynamic, thereby eliminating one - * more instance of the "number to vfs" mapping problem, but - * "11" is the order as taken from sys/mount.h - */ -} - -extern const struct vnodeopv_desc kernfs_vnodeop_opv_desc; - -const struct vnodeopv_desc * const kernfs_vnodeopv_descs[] = { - &kernfs_vnodeop_opv_desc, - NULL, -}; - -struct vfsops kernfs_vfsops = { - MOUNT_KERNFS, - kernfs_mount, - kernfs_start, - kernfs_unmount, - kernfs_root, - kernfs_quotactl, - kernfs_statvfs, - kernfs_sync, - kernfs_vget, - kernfs_fhtovp, - kernfs_vptofh, - kernfs_init, - kernfs_reinit, - kernfs_done, - NULL, - NULL, /* vfs_mountroot */ - kernfs_checkexp, - (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp, - vfs_stdextattrctl, - kernfs_vnodeopv_descs, -}; diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/kernfs/kernfs_vnops.c mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_vnops.c --- NetBSD-3.1/sys/miscfs/kernfs/kernfs_vnops.c 2005-11-24 22:11:11.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/kernfs/kernfs_vnops.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1524 +0,0 @@ -/* $NetBSD: kernfs_vnops.c,v 1.107.2.4 2005/11/24 22:11:11 tron Exp $ */ - -/* - * 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. 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. - * - * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95 - */ - -/* - * Kernel parameter filesystem (/kern) - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.107.2.4 2005/11/24 22:11:11 tron Exp $"); - -#ifdef _KERNEL_OPT -#include "opt_ipsec.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef IPSEC -#include -#include -#include -#include -#include -#endif - -#include - -#define KSTRING 256 /* Largest I/O available via this filesystem */ -#define UIO_MX 32 - -#define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH) -#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) -#define UREAD_MODE (S_IRUSR) -#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) -#define UDIR_MODE (S_IRUSR|S_IXUSR) - -#define N(s) sizeof(s)-1, s -const struct kern_target kern_targets[] = { -/* NOTE: The name must be less than UIO_MX-16 chars in length */ - /* name data tag type ro/rw */ - { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE }, - { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE }, - { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE }, - /* XXX cast away const */ - { DT_REG, N("copyright"), (void *)copyright, - KFSstring, VREG, READ_MODE }, - { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE }, - { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE }, -#ifdef IPSEC - { DT_DIR, N("ipsecsa"), 0, KFSipsecsadir, VDIR, UDIR_MODE }, - { DT_DIR, N("ipsecsp"), 0, KFSipsecspdir, VDIR, UDIR_MODE }, -#endif - { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE }, - { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE }, - { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE }, - { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE }, -#if 0 - { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE }, -#endif - { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE }, - { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE }, - { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE }, - /* XXX cast away const */ - { DT_REG, N("version"), (void *)version, - KFSstring, VREG, READ_MODE }, -}; -const struct kern_target subdir_targets[] = { -/* NOTE: The name must be less than UIO_MX-16 chars in length */ - /* name data tag type ro/rw */ - { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE }, - { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE }, -}; -#ifdef IPSEC -const struct kern_target ipsecsa_targets[] = { -/* NOTE: The name must be less than UIO_MX-16 chars in length */ - /* name data tag type ro/rw */ - { DT_DIR, N("."), 0, KFSipsecsadir, VDIR, DIR_MODE }, - { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE }, -}; -const struct kern_target ipsecsp_targets[] = { -/* NOTE: The name must be less than UIO_MX-16 chars in length */ - /* name data tag type ro/rw */ - { DT_DIR, N("."), 0, KFSipsecspdir, VDIR, DIR_MODE }, - { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE }, -}; -const struct kern_target ipsecsa_kt = - { DT_DIR, N(""), 0, KFSipsecsa, VREG, UREAD_MODE }; -const struct kern_target ipsecsp_kt = - { DT_DIR, N(""), 0, KFSipsecsp, VREG, UREAD_MODE }; -#endif -#undef N -SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets = - SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets); -int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); -const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); -#ifdef IPSEC -int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]); -int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]); -int nkern_dirs = 4; /* 2 extra subdirs */ -#else -int nkern_dirs = 2; -#endif - -int kernfs_try_fileop(kfstype, kfsfileop, void *, int); -int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *, - size_t, int); - -static int kernfs_default_xwrite(void *v); -static int kernfs_default_fileop_getattr(void *); - -/* must include all fileop's */ -const struct kernfs_fileop kernfs_default_fileops[] = { - { .kf_fileop = KERNFS_XWRITE }, - { .kf_fileop = KERNFS_FILEOP_OPEN }, - { .kf_fileop = KERNFS_FILEOP_GETATTR, - .kf_genop = {kernfs_default_fileop_getattr} }, - { .kf_fileop = KERNFS_FILEOP_IOCTL }, - { .kf_fileop = KERNFS_FILEOP_CLOSE }, - { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} }, -}; - -int kernfs_lookup __P((void *)); -#define kernfs_create genfs_eopnotsupp -#define kernfs_mknod genfs_eopnotsupp -int kernfs_open __P((void *)); -int kernfs_close __P((void *)); -int kernfs_access __P((void *)); -int kernfs_getattr __P((void *)); -int kernfs_setattr __P((void *)); -int kernfs_read __P((void *)); -int kernfs_write __P((void *)); -#define kernfs_fcntl genfs_fcntl -int kernfs_ioctl __P((void *)); -#define kernfs_poll genfs_poll -#define kernfs_revoke genfs_revoke -#define kernfs_fsync genfs_nullop -#define kernfs_seek genfs_nullop -#define kernfs_remove genfs_eopnotsupp -int kernfs_link __P((void *)); -#define kernfs_rename genfs_eopnotsupp -#define kernfs_mkdir genfs_eopnotsupp -#define kernfs_rmdir genfs_eopnotsupp -int kernfs_symlink __P((void *)); -int kernfs_readdir __P((void *)); -#define kernfs_readlink genfs_eopnotsupp -#define kernfs_abortop genfs_abortop -int kernfs_inactive __P((void *)); -int kernfs_reclaim __P((void *)); -#define kernfs_lock genfs_lock -#define kernfs_unlock genfs_unlock -#define kernfs_bmap genfs_badop -#define kernfs_strategy genfs_badop -int kernfs_print __P((void *)); -#define kernfs_islocked genfs_islocked -int kernfs_pathconf __P((void *)); -#define kernfs_advlock genfs_einval -#define kernfs_blkatoff genfs_eopnotsupp -#define kernfs_valloc genfs_eopnotsupp -#define kernfs_vfree genfs_nullop -#define kernfs_truncate genfs_eopnotsupp -#define kernfs_update genfs_nullop -#define kernfs_bwrite genfs_eopnotsupp -#define kernfs_putpages genfs_putpages - -static int kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *)); -static int kernfs_xwrite __P((const struct kernfs_node *, char *, size_t)); - -int (**kernfs_vnodeop_p) __P((void *)); -const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { - { &vop_default_desc, vn_default_error }, - { &vop_lookup_desc, kernfs_lookup }, /* lookup */ - { &vop_create_desc, kernfs_create }, /* create */ - { &vop_mknod_desc, kernfs_mknod }, /* mknod */ - { &vop_open_desc, kernfs_open }, /* open */ - { &vop_close_desc, kernfs_close }, /* close */ - { &vop_access_desc, kernfs_access }, /* access */ - { &vop_getattr_desc, kernfs_getattr }, /* getattr */ - { &vop_setattr_desc, kernfs_setattr }, /* setattr */ - { &vop_read_desc, kernfs_read }, /* read */ - { &vop_write_desc, kernfs_write }, /* write */ - { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */ - { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ - { &vop_poll_desc, kernfs_poll }, /* poll */ - { &vop_revoke_desc, kernfs_revoke }, /* revoke */ - { &vop_fsync_desc, kernfs_fsync }, /* fsync */ - { &vop_seek_desc, kernfs_seek }, /* seek */ - { &vop_remove_desc, kernfs_remove }, /* remove */ - { &vop_link_desc, kernfs_link }, /* link */ - { &vop_rename_desc, kernfs_rename }, /* rename */ - { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ - { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ - { &vop_symlink_desc, kernfs_symlink }, /* symlink */ - { &vop_readdir_desc, kernfs_readdir }, /* readdir */ - { &vop_readlink_desc, kernfs_readlink }, /* readlink */ - { &vop_abortop_desc, kernfs_abortop }, /* abortop */ - { &vop_inactive_desc, kernfs_inactive }, /* inactive */ - { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ - { &vop_lock_desc, kernfs_lock }, /* lock */ - { &vop_unlock_desc, kernfs_unlock }, /* unlock */ - { &vop_bmap_desc, kernfs_bmap }, /* bmap */ - { &vop_strategy_desc, kernfs_strategy }, /* strategy */ - { &vop_print_desc, kernfs_print }, /* print */ - { &vop_islocked_desc, kernfs_islocked }, /* islocked */ - { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */ - { &vop_advlock_desc, kernfs_advlock }, /* advlock */ - { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */ - { &vop_valloc_desc, kernfs_valloc }, /* valloc */ - { &vop_vfree_desc, kernfs_vfree }, /* vfree */ - { &vop_truncate_desc, kernfs_truncate }, /* truncate */ - { &vop_update_desc, kernfs_update }, /* update */ - { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ - { &vop_putpages_desc, kernfs_putpages }, /* putpages */ - { NULL, NULL } -}; -const struct vnodeopv_desc kernfs_vnodeop_opv_desc = - { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; - -static __inline int -kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b) -{ - if (a->kf_type < b->kf_type) - return -1; - if (a->kf_type > b->kf_type) - return 1; - if (a->kf_fileop < b->kf_fileop) - return -1; - if (a->kf_fileop > b->kf_fileop) - return 1; - return (0); -} - -SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree = - SPLAY_INITIALIZER(kfsfileoptree); -SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); -SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); - -kfstype -kernfs_alloctype(int nkf, const struct kernfs_fileop *kf) -{ - static u_char nextfreetype = KFSlasttype; - struct kernfs_fileop *dkf, *fkf, skf; - int i; - - /* XXX need to keep track of dkf's memory if we support - deallocating types */ - dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK); - memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops)); - - for (i = 0; i < sizeof(kernfs_default_fileops) / - sizeof(kernfs_default_fileops[0]); i++) { - dkf[i].kf_type = nextfreetype; - SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]); - } - - for (i = 0; i < nkf; i++) { - skf.kf_type = nextfreetype; - skf.kf_fileop = kf[i].kf_fileop; - if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) - fkf->kf_genop = kf[i].kf_genop; - } - - return nextfreetype++; -} - -int -kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error) -{ - struct kernfs_fileop *kf, skf; - - skf.kf_type = type; - skf.kf_fileop = fileop; - if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) - if (kf->kf_vop) - return kf->kf_vop(v); - return error; -} - -int -kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *buf, - size_t len, int error) -{ - struct kernfs_fileop *kf, skf; - - skf.kf_type = type; - skf.kf_fileop = KERNFS_XWRITE; - if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) - if (kf->kf_xwrite) - return kf->kf_xwrite(kfs, buf, len); - return error; -} - -int -kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt) -{ - struct kernfs_subdir *ks, *parent; - - if (pkt == NULL) { - SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue); - nkern_targets++; - if (dkt->dkt_kt.kt_vtype == VDIR) - nkern_dirs++; - } else { - parent = (struct kernfs_subdir *)pkt->kt_data; - SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue); - parent->ks_nentries++; - if (dkt->dkt_kt.kt_vtype == VDIR) - parent->ks_dirs++; - } - if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) { - ks = malloc(sizeof(struct kernfs_subdir), - M_TEMP, M_WAITOK); - SIMPLEQ_INIT(&ks->ks_entries); - ks->ks_nentries = 2; /* . and .. */ - ks->ks_dirs = 2; - ks->ks_parent = pkt ? pkt : &kern_targets[0]; - dkt->dkt_kt.kt_data = ks; - } - return 0; -} - -static int -kernfs_xread(kfs, off, bufp, len, wrlen) - struct kernfs_node *kfs; - int off; - char **bufp; - size_t len; - size_t *wrlen; -{ - const struct kern_target *kt; -#ifdef IPSEC - struct mbuf *m; -#endif - - kt = kfs->kfs_kt; - - switch (kfs->kfs_type) { - case KFStime: { - struct timeval tv; - - microtime(&tv); - snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec); - break; - } - - case KFSint: { - int *ip = kt->kt_data; - - snprintf(*bufp, len, "%d\n", *ip); - break; - } - - case KFSstring: { - char *cp = kt->kt_data; - - *bufp = cp; - break; - } - - case KFSmsgbuf: { - long n; - - /* - * deal with cases where the message buffer has - * become corrupted. - */ - if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { - msgbufenabled = 0; - return (ENXIO); - } - - /* - * Note that reads of /kern/msgbuf won't necessarily yield - * consistent results, if the message buffer is modified - * while the read is in progress. The worst that can happen - * is that incorrect data will be read. There's no way - * that this can crash the system unless the values in the - * message buffer header are corrupted, but that'll cause - * the system to die anyway. - */ - if (off >= msgbufp->msg_bufs) { - *wrlen = 0; - return (0); - } - n = msgbufp->msg_bufx + off; - if (n >= msgbufp->msg_bufs) - n -= msgbufp->msg_bufs; - len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); - *bufp = msgbufp->msg_bufc + n; - *wrlen = len; - return (0); - } - - case KFShostname: { - char *cp = hostname; - int xlen = hostnamelen; - - if (xlen >= (len - 2)) - return (EINVAL); - - memcpy(*bufp, cp, xlen); - (*bufp)[xlen] = '\n'; - (*bufp)[xlen+1] = '\0'; - len = strlen(*bufp); - break; - } - - case KFSavenrun: - averunnable.fscale = FSCALE; - snprintf(*bufp, len, "%d %d %d %ld\n", - averunnable.ldavg[0], averunnable.ldavg[1], - averunnable.ldavg[2], averunnable.fscale); - break; - -#ifdef IPSEC - case KFSipsecsa: - /* - * Note that SA configuration could be changed during the - * read operation, resulting in garbled output. - */ - m = key_setdumpsa_spi(htonl(kfs->kfs_value)); - if (!m) - return (ENOBUFS); - if (off >= m->m_pkthdr.len) { - *wrlen = 0; - m_freem(m); - return (0); - } - if (len > m->m_pkthdr.len - off) - len = m->m_pkthdr.len - off; - m_copydata(m, off, len, *bufp); - *wrlen = len; - m_freem(m); - return (0); - - case KFSipsecsp: - /* - * Note that SP configuration could be changed during the - * read operation, resulting in garbled output. - */ - if (!kfs->kfs_v) { - struct secpolicy *sp; - - sp = key_getspbyid(kfs->kfs_value); - if (sp) - kfs->kfs_v = sp; - else - return (ENOENT); - } - m = key_setdumpsp((struct secpolicy *)kfs->kfs_v, - SADB_X_SPDGET, 0, 0); - if (!m) - return (ENOBUFS); - if (off >= m->m_pkthdr.len) { - *wrlen = 0; - m_freem(m); - return (0); - } - if (len > m->m_pkthdr.len - off) - len = m->m_pkthdr.len - off; - m_copydata(m, off, len, *bufp); - *wrlen = len; - m_freem(m); - return (0); -#endif - - default: - *wrlen = 0; - return (0); - } - - len = strlen(*bufp); - if (len <= off) - *wrlen = 0; - else { - *bufp += off; - *wrlen = len - off; - } - return (0); -} - -static int -kernfs_xwrite(kfs, buf, len) - const struct kernfs_node *kfs; - char *buf; - size_t len; -{ - - switch (kfs->kfs_type) { - case KFShostname: - if (buf[len-1] == '\n') - --len; - memcpy(hostname, buf, len); - hostname[len] = '\0'; - hostnamelen = (size_t) len; - return (0); - - default: - return kernfs_try_xwrite(kfs->kfs_type, kfs, buf, len, EIO); - } -} - - -/* - * vp is the current namei directory - * ndp is the name to locate in that directory... - */ -int -kernfs_lookup(v) - void *v; -{ - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap = v; - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - const char *pname = cnp->cn_nameptr; - const struct kernfs_node *kfs; - const struct kern_target *kt; - const struct dyn_kern_target *dkt; - const struct kernfs_subdir *ks; - int error, i, wantpunlock; -#ifdef IPSEC - char *ep; - u_int32_t id; -#endif - - *vpp = NULLVP; - cnp->cn_flags &= ~PDIRUNLOCK; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - return (0); - } - - wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN)); - kfs = VTOKERN(dvp); - switch (kfs->kfs_type) { - case KFSkern: - /* - * Shouldn't get here with .. in the root node. - */ - if (cnp->cn_flags & ISDOTDOT) - return (EIO); - - for (i = 0; i < static_nkern_targets; i++) { - kt = &kern_targets[i]; - if (cnp->cn_namelen == kt->kt_namlen && - memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) - goto found; - } - SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) { - if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && - memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { - kt = &dkt->dkt_kt; - goto found; - } - } - break; - - found: - error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0); - if ((error == 0) && wantpunlock) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - - case KFSsubdir: - ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; - if (cnp->cn_flags & ISDOTDOT) { - kt = ks->ks_parent; - goto found; - } - - SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) { - if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && - memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { - kt = &dkt->dkt_kt; - goto found; - } - } - break; - -#ifdef IPSEC - case KFSipsecsadir: - if (cnp->cn_flags & ISDOTDOT) { - kt = &kern_targets[0]; - goto found; - } - - for (i = 2; i < nipsecsa_targets; i++) { - kt = &ipsecsa_targets[i]; - if (cnp->cn_namelen == kt->kt_namlen && - memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) - goto found; - } - - ep = NULL; - id = strtoul(pname, &ep, 10); - if (!ep || *ep || ep == pname) - break; - - error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id); - if ((error == 0) && wantpunlock) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - - case KFSipsecspdir: - if (cnp->cn_flags & ISDOTDOT) { - kt = &kern_targets[0]; - goto found; - } - - for (i = 2; i < nipsecsp_targets; i++) { - kt = &ipsecsp_targets[i]; - if (cnp->cn_namelen == kt->kt_namlen && - memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) - goto found; - } - - ep = NULL; - id = strtoul(pname, &ep, 10); - if (!ep || *ep || ep == pname) - break; - - error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id); - if ((error == 0) && wantpunlock) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); -#endif - - default: - return (ENOTDIR); - } - - return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); -} - -int -kernfs_open(v) - void *v; -{ - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); -#ifdef IPSEC - struct mbuf *m; - struct secpolicy *sp; -#endif - - switch (kfs->kfs_type) { -#ifdef IPSEC - case KFSipsecsa: - m = key_setdumpsa_spi(htonl(kfs->kfs_value)); - if (m) { - m_freem(m); - return (0); - } else - return (ENOENT); - - case KFSipsecsp: - sp = key_getspbyid(kfs->kfs_value); - if (sp) { - kfs->kfs_v = sp; - return (0); - } else - return (ENOENT); -#endif - - default: - return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, - v, 0); - } -} - -int -kernfs_close(v) - void *v; -{ - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - - switch (kfs->kfs_type) { -#ifdef IPSEC - case KFSipsecsp: - key_freesp((struct secpolicy *)kfs->kfs_v); - break; -#endif - - default: - return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, - v, 0); - } - - return (0); -} - -int -kernfs_access(v) - void *v; -{ - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vattr va; - int error; - - if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) - return (error); - - return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid, - ap->a_mode, ap->a_cred)); -} - -static int -kernfs_default_fileop_getattr(v) - void *v; -{ - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vattr *vap = ap->a_vap; - - vap->va_nlink = 1; - vap->va_bytes = vap->va_size = 0; - - return 0; -} - -int -kernfs_getattr(v) - void *v; -{ - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - struct kernfs_subdir *ks; - struct vattr *vap = ap->a_vap; - int error = 0; - char strbuf[KSTRING], *buf; - size_t nread, total; - - VATTR_NULL(vap); - vap->va_type = ap->a_vp->v_type; - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_mode = kfs->kfs_mode; - vap->va_fileid = kfs->kfs_fileno; - vap->va_flags = 0; - vap->va_size = 0; - vap->va_blocksize = DEV_BSIZE; - /* - * Make all times be current TOD, except for the "boottime" node. - * Avoid microtime(9), it's slow. - * We don't guard the read from time(9) with splclock(9) since we - * don't actually need to be THAT sure the access is atomic. - */ - if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 && - !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) { - TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime); - } else { - TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime); - } - vap->va_atime = vap->va_mtime = vap->va_ctime; - vap->va_gen = 0; - vap->va_flags = 0; - vap->va_rdev = 0; - vap->va_bytes = 0; - - switch (kfs->kfs_type) { - case KFSkern: - vap->va_nlink = nkern_dirs; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; - - case KFSroot: - vap->va_nlink = 1; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; - - case KFSsubdir: - ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; - vap->va_nlink = ks->ks_dirs; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; - - case KFSnull: - case KFStime: - case KFSint: - case KFSstring: - case KFShostname: - case KFSavenrun: - case KFSdevice: - case KFSmsgbuf: -#ifdef IPSEC - case KFSipsecsa: - case KFSipsecsp: -#endif - vap->va_nlink = 1; - total = 0; - do { - buf = strbuf; - error = kernfs_xread(kfs, total, &buf, - sizeof(strbuf), &nread); - total += nread; - } while (error == 0 && nread != 0); - vap->va_bytes = vap->va_size = total; - break; - -#ifdef IPSEC - case KFSipsecsadir: - case KFSipsecspdir: - vap->va_nlink = 2; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; -#endif - - default: - error = kernfs_try_fileop(kfs->kfs_type, - KERNFS_FILEOP_GETATTR, v, EINVAL); - break; - } - - return (error); -} - -/*ARGSUSED*/ -int -kernfs_setattr(v) - void *v; -{ - - /* - * Silently ignore attribute changes. - * This allows for open with truncate to have no - * effect until some data is written. I want to - * do it this way because all writes are atomic. - */ - return (0); -} - -int -kernfs_read(v) - void *v; -{ - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap = v; - struct uio *uio = ap->a_uio; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - char strbuf[KSTRING], *bf; - int off; - size_t len; - int error; - - if (ap->a_vp->v_type == VDIR) - return (EOPNOTSUPP); - - off = (int)uio->uio_offset; - /* Don't allow negative offsets */ - if (off < 0) - return EINVAL; - - bf = strbuf; - if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0) - error = uiomove(bf, len, uio); - return (error); -} - -static int -kernfs_default_xwrite(v) - void *v; -{ - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - struct uio *uio = ap->a_uio; - int error, xlen; - char strbuf[KSTRING]; - - if (uio->uio_offset != 0) - return (EINVAL); - - xlen = min(uio->uio_resid, KSTRING-1); - if ((error = uiomove(strbuf, xlen, uio)) != 0) - return (error); - - if (uio->uio_resid != 0) - return (EIO); - - strbuf[xlen] = '\0'; - xlen = strlen(strbuf); - return (kernfs_xwrite(kfs, strbuf, xlen)); -} - -int -kernfs_write(v) - void *v; -{ - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - - return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0); -} - -int -kernfs_ioctl(v) - void *v; -{ - struct vop_ioctl_args /* { - const struct vnodeop_desc *a_desc; - struct vnode *a_vp; - u_long a_command; - void *a_data; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - - return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v, - EPASSTHROUGH); -} - -static int -kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, - u_int32_t value, struct vop_readdir_args *ap) -{ - struct kernfs_node *kfs; - struct vnode *vp; - int error; - - if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt, - value)) != 0) - return error; - if (kt->kt_tag == KFSdevice) { - struct vattr va; - if ((error = VOP_GETATTR(vp, &va, ap->a_cred, - ap->a_uio->uio_segflg == UIO_USERSPACE ? - ap->a_uio->uio_procp : &proc0)) != 0) - return (error); - d->d_fileno = va.va_fileid; - } else { - kfs = VTOKERN(vp); - d->d_fileno = kfs->kfs_fileno; - } - vput(vp); - return 0; -} - -static int -kernfs_setdirentfileno(struct dirent *d, off_t entry, - struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt, - const struct kern_target *kt, struct vop_readdir_args *ap) -{ - const struct kern_target *ikt; - int error; - - switch (entry) { - case 0: - d->d_fileno = thisdir_kfs->kfs_fileno; - return 0; - case 1: - ikt = parent_kt; - break; - default: - ikt = kt; - break; - } - if (ikt != thisdir_kfs->kfs_kt) { - if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0) - return error; - } else - d->d_fileno = thisdir_kfs->kfs_fileno; - return 0; -} - -int -kernfs_readdir(v) - void *v; -{ - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - off_t **a_cookies; - int a_*ncookies; - } */ *ap = v; - struct uio *uio = ap->a_uio; - struct dirent d; - struct kernfs_node *kfs = VTOKERN(ap->a_vp); - const struct kern_target *kt; - const struct dyn_kern_target *dkt = NULL; - const struct kernfs_subdir *ks; - off_t i, j; - int error; - off_t *cookies = NULL; - int ncookies = 0, n; -#ifdef IPSEC - struct secasvar *sav, *sav2; - struct secpolicy *sp; -#endif - - if (uio->uio_resid < UIO_MX) - return (EINVAL); - if (uio->uio_offset < 0) - return (EINVAL); - - error = 0; - i = uio->uio_offset; - memset(&d, 0, sizeof(d)); - d.d_reclen = UIO_MX; - ncookies = uio->uio_resid / UIO_MX; - - switch (kfs->kfs_type) { - case KFSkern: - if (i >= nkern_targets) - return (0); - - if (ap->a_ncookies) { - ncookies = min(ncookies, (nkern_targets - i)); - cookies = malloc(ncookies * sizeof(off_t), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - } - - n = 0; - for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) { - if (i < static_nkern_targets) - kt = &kern_targets[i]; - else { - if (dkt == NULL) { - dkt = SIMPLEQ_FIRST(&dyn_kern_targets); - for (j = static_nkern_targets; j < i && - dkt != NULL; j++) - dkt = SIMPLEQ_NEXT(dkt, dkt_queue); - if (j != i) - break; - } else { - dkt = SIMPLEQ_NEXT(dkt, dkt_queue); - if (dkt == NULL) - break; - } - kt = &dkt->dkt_kt; - } - if (kt->kt_tag == KFSdevice) { - dev_t *dp = kt->kt_data; - struct vnode *fvp; - - if (*dp == NODEV || - !vfinddev(*dp, kt->kt_vtype, &fvp)) - continue; - } - d.d_namlen = kt->kt_namlen; - if ((error = kernfs_setdirentfileno(&d, i, kfs, - &kern_targets[0], kt, ap)) != 0) - break; - memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); - d.d_type = kt->kt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - } - ncookies = n; - break; - - case KFSroot: - if (i >= 2) - return 0; - - if (ap->a_ncookies) { - ncookies = min(ncookies, (2 - i)); - cookies = malloc(ncookies * sizeof(off_t), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - } - - n = 0; - for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { - kt = &kern_targets[i]; - d.d_namlen = kt->kt_namlen; - d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); - memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); - d.d_type = kt->kt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - } - ncookies = n; - break; - - case KFSsubdir: - ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; - if (i >= ks->ks_nentries) - return (0); - - if (ap->a_ncookies) { - ncookies = min(ncookies, (ks->ks_nentries - i)); - cookies = malloc(ncookies * sizeof(off_t), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - } - - dkt = SIMPLEQ_FIRST(&ks->ks_entries); - for (j = 0; j < i && dkt != NULL; j++) - dkt = SIMPLEQ_NEXT(dkt, dkt_queue); - n = 0; - for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { - if (i < 2) - kt = &subdir_targets[i]; - else { - /* check if ks_nentries lied to us */ - if (dkt == NULL) - break; - kt = &dkt->dkt_kt; - dkt = SIMPLEQ_NEXT(dkt, dkt_queue); - } - if (kt->kt_tag == KFSdevice) { - dev_t *dp = kt->kt_data; - struct vnode *fvp; - - if (*dp == NODEV || - !vfinddev(*dp, kt->kt_vtype, &fvp)) - continue; - } - d.d_namlen = kt->kt_namlen; - if ((error = kernfs_setdirentfileno(&d, i, kfs, - ks->ks_parent, kt, ap)) != 0) - break; - memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); - d.d_type = kt->kt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - } - ncookies = n; - break; - -#ifdef IPSEC - case KFSipsecsadir: - /* count SA in the system */ - n = 0; - TAILQ_FOREACH(sav, &satailq, tailq) { - for (sav2 = TAILQ_FIRST(&satailq); - sav2 != sav; - sav2 = TAILQ_NEXT(sav2, tailq)) { - if (sav->spi == sav2->spi) { - /* multiple SA with same SPI */ - break; - } - } - if (sav == sav2 || sav->spi != sav2->spi) - n++; - } - - if (i >= nipsecsa_targets + n) - return (0); - - if (ap->a_ncookies) { - ncookies = min(ncookies, (n - i)); - cookies = malloc(ncookies * sizeof(off_t), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - } - - n = 0; - for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) { - kt = &ipsecsa_targets[i]; - d.d_namlen = kt->kt_namlen; - if ((error = kernfs_setdirentfileno(&d, i, kfs, - &kern_targets[0], kt, ap)) != 0) - break; - memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); - d.d_type = kt->kt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - } - if (error) { - ncookies = n; - break; - } - - TAILQ_FOREACH(sav, &satailq, tailq) { - for (sav2 = TAILQ_FIRST(&satailq); - sav2 != sav; - sav2 = TAILQ_NEXT(sav2, tailq)) { - if (sav->spi == sav2->spi) { - /* multiple SA with same SPI */ - break; - } - } - if (sav != sav2 && sav->spi == sav2->spi) - continue; - if (uio->uio_resid < UIO_MX) - break; - if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt, - sav->spi, ap)) != 0) - break; - d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), - "%u", ntohl(sav->spi)); - d.d_type = DT_REG; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - i++; - } - ncookies = n; - break; - - case KFSipsecspdir: - /* count SP in the system */ - n = 0; - TAILQ_FOREACH(sp, &sptailq, tailq) - n++; - - if (i >= nipsecsp_targets + n) - return (0); - - if (ap->a_ncookies) { - ncookies = min(ncookies, (n - i)); - cookies = malloc(ncookies * sizeof(off_t), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - } - - n = 0; - for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) { - kt = &ipsecsp_targets[i]; - d.d_namlen = kt->kt_namlen; - if ((error = kernfs_setdirentfileno(&d, i, kfs, - &kern_targets[0], kt, ap)) != 0) - break; - memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); - d.d_type = kt->kt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - } - if (error) { - ncookies = n; - break; - } - - TAILQ_FOREACH(sp, &sptailq, tailq) { - if (uio->uio_resid < UIO_MX) - break; - if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt, - sp->id, ap)) != 0) - break; - d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), - "%u", sp->id); - d.d_type = DT_REG; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - n++; - i++; - } - ncookies = n; - break; -#endif - - default: - error = ENOTDIR; - break; - } - - if (ap->a_ncookies) { - if (error) { - if (cookies) - free(*ap->a_cookies, M_TEMP); - *ap->a_ncookies = 0; - *ap->a_cookies = NULL; - } else - *ap->a_ncookies = ncookies; - } - - uio->uio_offset = i; - return (error); -} - -int -kernfs_inactive(v) - void *v; -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - const struct kernfs_node *kfs = VTOKERN(ap->a_vp); -#ifdef IPSEC - struct mbuf *m; - struct secpolicy *sp; -#endif - - VOP_UNLOCK(vp, 0); - switch (kfs->kfs_type) { -#ifdef IPSEC - case KFSipsecsa: - m = key_setdumpsa_spi(htonl(kfs->kfs_value)); - if (m) - m_freem(m); - else - vgone(vp); - break; - case KFSipsecsp: - sp = key_getspbyid(kfs->kfs_value); - if (sp) - key_freesp(sp); - else { - /* should never happen as we hold a refcnt */ - vgone(vp); - } - break; -#endif - default: - break; - } - return (0); -} - -int -kernfs_reclaim(v) - void *v; -{ - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap = v; - - return (kernfs_freevp(ap->a_vp)); -} - -/* - * Return POSIX pathconf information applicable to special devices. - */ -int -kernfs_pathconf(v) - void *v; -{ - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - register_t *a_retval; - } */ *ap = v; - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = LINK_MAX; - return (0); - case _PC_MAX_CANON: - *ap->a_retval = MAX_CANON; - return (0); - case _PC_MAX_INPUT: - *ap->a_retval = MAX_INPUT; - return (0); - case _PC_PIPE_BUF: - *ap->a_retval = PIPE_BUF; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_VDISABLE: - *ap->a_retval = _POSIX_VDISABLE; - return (0); - case _PC_SYNC_IO: - *ap->a_retval = 1; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -/* - * Print out the contents of a /dev/fd vnode. - */ -/* ARGSUSED */ -int -kernfs_print(v) - void *v; -{ - - printf("tag VT_KERNFS, kernfs vnode\n"); - return (0); -} - -int -kernfs_link(v) - void *v; -{ - struct vop_link_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EROFS); -} - -int -kernfs_symlink(v) - void *v; -{ - struct vop_symlink_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - char *a_target; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EROFS); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/Makefile mult-netbsd-3.1/sys/miscfs/procfs/Makefile --- NetBSD-3.1/sys/miscfs/procfs/Makefile 1998-06-13 00:23:04.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -# $NetBSD: Makefile,v 1.1 1998/06/12 23:23:04 cgd Exp $ - -INCSDIR= /usr/include/miscfs/procfs - -INCS= procfs.h - -.include diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/files.procfs mult-netbsd-3.1/sys/miscfs/procfs/files.procfs --- NetBSD-3.1/sys/miscfs/procfs/files.procfs 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/files.procfs 1970-01-01 01:00:00.000000000 +0100 @@ -1,17 +0,0 @@ -# $NetBSD: files.procfs,v 1.4 2005/02/26 22:59:00 perry Exp $ - -deffs PROCFS - -file miscfs/procfs/procfs_cmdline.c procfs -file miscfs/procfs/procfs_ctl.c procfs -file miscfs/procfs/procfs_fd.c procfs -file miscfs/procfs/procfs_fpregs.c procfs -file miscfs/procfs/procfs_linux.c procfs -file miscfs/procfs/procfs_map.c procfs -file miscfs/procfs/procfs_mem.c procfs -file miscfs/procfs/procfs_note.c procfs -file miscfs/procfs/procfs_regs.c procfs -file miscfs/procfs/procfs_status.c procfs -file miscfs/procfs/procfs_subr.c procfs -file miscfs/procfs/procfs_vfsops.c procfs -file miscfs/procfs/procfs_vnops.c procfs diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs.h mult-netbsd-3.1/sys/miscfs/procfs/procfs.h --- NetBSD-3.1/sys/miscfs/procfs/procfs.h 2004-09-20 18:53:08.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,244 +0,0 @@ -/* $NetBSD: procfs.h,v 1.56 2004/09/20 17:53:08 jdolecek Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -/* This also pulls in __HAVE_PROCFS_MACHDEP */ -#include - -#ifdef _KERNEL -/* - * The different types of node in a procfs filesystem - */ -typedef enum { - PFSroot, /* the filesystem root */ - PFScurproc, /* symbolic link for curproc */ - PFSself, /* like curproc, but this is the Linux name */ - PFSproc, /* a process-specific sub-directory */ - PFSfile, /* the executable file */ - PFSmem, /* the process's memory image */ - PFSregs, /* the process's register set */ - PFSfpregs, /* the process's FP register set */ - PFSctl, /* process control */ - PFSstat, /* process status (if -o linux) */ - PFSstatus, /* process status */ - PFSnote, /* process notifier */ - PFSnotepg, /* process group notifier */ - PFSmap, /* memory map */ - PFScmdline, /* process command line args */ - PFSmeminfo, /* system memory info (if -o linux) */ - PFScpuinfo, /* CPU info (if -o linux) */ - PFSmaps, /* memory map, Linux style (if -o linux) */ - PFSfd, /* a directory containing the processes open fd's */ - PFSuptime, /* elapsed time since (if -o linux) */ - PFSmounts, /* mounted filesystems (if -o linux) */ -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODE_TYPES -#endif -} pfstype; - -/* - * control data for the proc file system. - */ -struct pfsnode { - LIST_ENTRY(pfsnode) pfs_hash; /* hash chain */ - struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ - pfstype pfs_type; /* type of procfs node */ - pid_t pfs_pid; /* associated process */ - int pfs_fd; /* associated fd if not -1 */ - mode_t pfs_mode; /* mode bits for stat() */ - u_long pfs_flags; /* open flags */ - u_long pfs_fileno; /* unique file id */ -}; - -#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 */ - -#endif /* _KERNEL */ - -struct procfs_args { - int version; - int flags; -}; - -#define PROCFS_ARGSVERSION 1 - -#define PROCFSMNT_LINUXCOMPAT 0x01 - -#define PROCFSMNT_BITS "\177\20" \ - "b\00linuxcompat\0" - -/* - * Kernel stuff follows - */ -#ifdef _KERNEL -#define CNEQ(cnp, s, len) \ - ((cnp)->cn_namelen == (len) && \ - (memcmp((s), (cnp)->cn_nameptr, (len)) == 0)) - -#define UIO_MX 32 - -#define PROCFS_FILENO(pid, type, fd) \ - (((type) < PFSproc) ? ((type) + 2) : \ - (((fd) == -1) ? ((((pid)+1) << 5) + ((int) (type))) : \ - ((((pid)+1) << 16) | ((fd) << 5) | ((int) (type))))) - -struct procfsmount { - void *pmnt_exechook; - int pmnt_flags; -}; - -#define VFSTOPROC(mp) ((struct procfsmount *)(mp)->mnt_data) - -/* - * 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 *)); -const vfs_namemap_t *vfs_findname __P((const vfs_namemap_t *, const char *, int)); - -#define PFIND(pid) ((pid) ? pfind(pid) : &proc0) -int procfs_freevp __P((struct vnode *)); -int procfs_allocvp __P((struct mount *, struct vnode **, pid_t, pfstype, int)); -int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_doregs __P((struct proc *, struct lwp *, struct pfsnode *, - struct uio *)); -int procfs_dofpregs __P((struct proc *, struct lwp *, struct pfsnode *, - struct uio *)); -int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_doctl __P((struct proc *, struct lwp *, struct pfsnode *, - struct uio *)); -int procfs_do_pid_stat __P((struct proc *, struct lwp *, struct pfsnode *, - struct uio *)); -int procfs_dostatus __P((struct proc *, struct lwp *, struct pfsnode *, - struct uio *)); -int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *, int)); -int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_domeminfo __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_docpuinfo __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_dofd __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_douptime __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); -int procfs_domounts __P((struct proc *, struct proc *, struct pfsnode *, - struct uio *)); - -void procfs_revoke_vnodes __P((struct proc *, void *)); -void procfs_hashinit __P((void)); -void procfs_hashreinit __P((void)); -void procfs_hashdone __P((void)); -int procfs_getfp __P((struct pfsnode *, struct proc **, struct file **)); - -/* functions to check whether or not files should be displayed */ -int procfs_validfile __P((struct proc *, struct mount *)); -int procfs_validfpregs __P((struct proc *, struct mount *)); -int procfs_validregs __P((struct proc *, struct mount *)); -int procfs_validmap __P((struct proc *, struct mount *)); - -int procfs_rw __P((void *)); - -int procfs_getcpuinfstr __P((char *, int *)); - -#define PROCFS_LOCKED 0x01 -#define PROCFS_WANT 0x02 - -extern int (**procfs_vnodeop_p) __P((void *)); -extern struct vfsops procfs_vfsops; - -int procfs_root __P((struct mount *, struct vnode **)); - -#ifdef __HAVE_PROCFS_MACHDEP -struct vattr; - -void procfs_machdep_allocvp(struct vnode *); -int procfs_machdep_rw(struct proc *, struct lwp *, struct pfsnode *, - struct uio *); -int procfs_machdep_getattr(struct vnode *, struct vattr *, struct proc *); -#endif - -#ifdef SYSCTL_SETUP_PROTO -SYSCTL_SETUP_PROTO(sysctl_vfs_procfs_setup); -#endif /* SYSCTL_SETUP_PROTO */ -#endif /* _KERNEL */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_cmdline.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_cmdline.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_cmdline.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_cmdline.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,190 +0,0 @@ -/* $NetBSD: procfs_cmdline.c,v 1.19 2005/02/26 22:59:00 perry Exp $ */ - -/* - * Copyright (c) 1999 Jaromir Dolecek - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek. - * - * 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 NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_cmdline.c,v 1.19 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * code for returning process's command line arguments - */ -int -procfs_docmdline(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - struct ps_strings pss; - int count, error; - size_t i, len, xlen, upper_bound; - struct uio auio; - struct iovec aiov; - vaddr_t argv; - char *arg; - - /* Don't allow writing. */ - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - /* - * Allocate a temporary buffer to hold the arguments. - */ - arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); - - /* - * Zombies don't have a stack, so we can't read their psstrings. - * System processes also don't have a user stack. This is what - * ps(1) would display. - */ - if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) { - len = snprintf(arg, PAGE_SIZE, "(%s)", p->p_comm); - error = uiomove_frombuf(arg, len, uio); - - free(arg, M_TEMP); - return (error); - } - - /* - * NOTE: Don't bother doing a process_checkioperm() here - * because the psstrings info is available by using ps(1), - * so it's not like there's anything to protect here. - */ - - /* - * Lock the process down in memory. - */ - /* XXXCDC: how should locking work here? */ - if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) { - free(arg, M_TEMP); - return (EFAULT); - } - p->p_vmspace->vm_refcnt++; /* XXX */ - - /* - * Read in the ps_strings structure. - */ - aiov.iov_base = &pss; - aiov.iov_len = sizeof(pss); - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_offset = (vaddr_t)p->p_psstr; - auio.uio_resid = sizeof(pss); - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_READ; - auio.uio_procp = NULL; - error = uvm_io(&p->p_vmspace->vm_map, &auio); - if (error) - goto bad; - - /* - * Now read the address of the argument vector. - */ - aiov.iov_base = &argv; - aiov.iov_len = sizeof(argv); - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_offset = (vaddr_t)pss.ps_argvstr; - auio.uio_resid = sizeof(argv); - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_READ; - auio.uio_procp = NULL; - error = uvm_io(&p->p_vmspace->vm_map, &auio); - if (error) - goto bad; - - /* - * Now copy in the actual argument vector, one page at a time, - * since we don't know how long the vector is (though, we do - * know how many NUL-terminated strings are in the vector). - */ - len = 0; - count = pss.ps_nargvstr; - upper_bound = round_page(uio->uio_offset + uio->uio_resid); - for (; count && len < upper_bound; len += xlen) { - aiov.iov_base = arg; - aiov.iov_len = PAGE_SIZE; - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_offset = argv + len; - xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK); - auio.uio_resid = xlen; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_READ; - auio.uio_procp = NULL; - error = uvm_io(&p->p_vmspace->vm_map, &auio); - if (error) - goto bad; - - for (i = 0; i < xlen && count != 0; i++) { - if (arg[i] == '\0') - count--; /* one full string */ - } - - if (count == 0) - i--; /* exclude the final NUL */ - - if (len + i > uio->uio_offset) { - /* Have data in this page, copy it out */ - error = uiomove(arg + uio->uio_offset - len, - i + len - uio->uio_offset, uio); - if (error || uio->uio_resid <= 0) - break; - } - } - - bad: - /* - * Release the process. - */ - uvmspace_free(p->p_vmspace); - - free(arg, M_TEMP); - return (error); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_ctl.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_ctl.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_ctl.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_ctl.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,376 +0,0 @@ -/* $NetBSD: procfs_ctl.c,v 1.28 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_ctl.c,v 1.28 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 const 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 const 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 }, -}; - -int procfs_control __P((struct proc *, struct lwp *, int, int)); - -/* Macros to clear/set/test flags. */ -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~(f) -#define ISSET(t, f) ((t) & (f)) - -int -procfs_control(curp, l, op, sig) - struct proc *curp; - struct lwp *l; - int op, sig; -{ - int s, error; - struct proc *p = l->l_proc; - - /* - * You cannot do anything to the process if it is currently exec'ing - */ - if (ISSET(p->p_flag, P_INEXEC)) - return (EAGAIN); - - switch (op) { - /* - * Attach - attaches the target process for debugging - * by the calling process. - */ - case PROCFS_CTL_ATTACH: - /* - * You can't attach to a process if: - * (1) it's the process that's doing the attaching, - */ - if (p->p_pid == curp->p_pid) - return (EINVAL); - - /* - * (2) it's already being traced, or - */ - if (ISSET(p->p_flag, P_TRACED)) - return (EBUSY); - - /* - * (3) it's not owned by you, or is set-id on exec - * (unless you're root), or... - */ - if ((p->p_cred->p_ruid != curp->p_cred->p_ruid || - ISSET(p->p_flag, P_SUGID)) && - (error = suser(curp->p_ucred, &curp->p_acflag)) != 0) - return (error); - - /* - * (4) ...it's init, which controls the security level - * of the entire system, and the system was not - * compiled with permanently insecure mode turned - * on. - */ - if (p == initproc && securelevel > -1) - return (EPERM); - break; - - /* - * 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. - * - * Note that the semantics of DETACH are different here - * from ptrace(2). - */ - case PROCFS_CTL_DETACH: - case PROCFS_CTL_WAIT: - /* - * You can't do what you want to the process if: - * (1) It's not being traced at all, - */ - if (!ISSET(p->p_flag, P_TRACED)) - return (EPERM); - - /* - * (2) it's being traced by ptrace(2) (which has - * different signal delivery semantics), or - */ - if (!ISSET(p->p_flag, P_FSTRACE)) - return (EBUSY); - - /* - * (3) it's not being traced by _you_. - */ - if (p->p_pptr != curp) - return (EBUSY); - break; - - default: - /* - * You can't do what you want to the process if: - * (1) It's not being traced at all, - */ - if (!ISSET(p->p_flag, P_TRACED)) - return (EPERM); - - /* - * (2) it's being traced by ptrace(2) (which has - * different signal delivery semantics), - */ - if (!ISSET(p->p_flag, P_FSTRACE)) - return (EBUSY); - - /* - * (3) it's not being traced by _you_, or - */ - if (p->p_pptr != curp) - return (EBUSY); - - /* - * (4) it's not currently stopped. - */ - if (p->p_stat != SSTOP || !ISSET(p->p_flag, P_WAITED)) - return (EBUSY); - break; - } - - /* Do single-step fixup if needed. */ - FIX_SSTEP(p); - - switch (op) { - case PROCFS_CTL_ATTACH: - /* - * 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. - */ - SET(p->p_flag, P_TRACED|P_FSTRACE); - p->p_opptr = p->p_pptr; - if (p->p_pptr != curp) { - p->p_pptr->p_flag |= P_CHTRACED; - proc_reparent(p, curp); - } - sig = SIGSTOP; - goto sendsig; - -#ifdef PT_STEP - case PROCFS_CTL_STEP: - /* - * Step. Let the target process execute a single instruction. - */ -#endif - case PROCFS_CTL_RUN: - case PROCFS_CTL_DETACH: -#ifdef PT_STEP - PHOLD(l); - error = process_sstep(l, op == PROCFS_CTL_STEP); - PRELE(l); - if (error) - return (error); -#endif - - if (op == PROCFS_CTL_DETACH) { - /* give process back to original parent */ - if (p->p_opptr != p->p_pptr) { - struct proc *pp = p->p_opptr; - proc_reparent(p, pp ? pp : initproc); - } - - /* not being traced any more */ - p->p_opptr = NULL; - CLR(p->p_flag, P_TRACED|P_FSTRACE|P_WAITED); - } - - sendsig: - /* Finally, deliver the requested signal (or none). */ - if (l->l_stat == LSSTOP) { - p->p_xstat = sig; - SCHED_LOCK(s); - setrunnable(l); - SCHED_UNLOCK(s); - } else { - if (sig != 0) - psignal(p, sig); - } - return (0); - - case PROCFS_CTL_WAIT: - /* - * Wait for the target process to stop. - */ - while (l->l_stat != LSSTOP && P_ZOMBIE(p)) { - error = tsleep(l, PWAIT|PCATCH, "procfsx", 0); - if (error) - return (error); - } - return (0); - } - - panic("procfs_control"); -} - -int -procfs_doctl(curp, l, pfs, uio) - struct proc *curp; - struct lwp *l; - struct pfsnode *pfs; - struct uio *uio; -{ - int xlen; - int error; - char msg[PROCFS_CTLLEN+1]; - const vfs_namemap_t *nm; - struct proc *p = l->l_proc; - - 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, l, nm->nm_val, 0); - } else { - nm = vfs_findname(signames, msg, xlen); - if (nm) { - if (ISSET(p->p_flag, P_TRACED) && - p->p_pptr == curp) - error = procfs_control(curp, l, PROCFS_CTL_RUN, - nm->nm_val); - else { - psignal(p, nm->nm_val); - error = 0; - } - } - } - - return (error); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_fd.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_fd.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_fd.c 2003-06-29 23:31:45.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_fd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,84 +0,0 @@ -/* $NetBSD: procfs_fd.c,v 1.5 2003/06/29 22:31:45 fvdl Exp $ */ - -/*- - * Copyright (c) 2003 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * 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 NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_fd.c,v 1.5 2003/06/29 22:31:45 fvdl Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -procfs_dofd(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - int error; - struct file *fp; - struct proc *pown; - off_t offs; - - if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) - return error; - - FILE_USE(fp); - - offs = fp->f_offset; - - switch (uio->uio_rw) { - case UIO_READ: - error = (*fp->f_ops->fo_read)(fp, &offs, uio, curp->p_ucred, 0); - break; - case UIO_WRITE: - error = (*fp->f_ops->fo_write)(fp, &offs, uio, curp->p_ucred,0); - break; - default: - panic("bad uio op"); - } - - FILE_UNUSE(fp, pown); - - return (error); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_fpregs.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_fpregs.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_fpregs.c 2003-08-07 17:32:41.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_fpregs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,105 +0,0 @@ -/* $NetBSD: procfs_fpregs.c,v 1.14 2003/08/07 16:32:41 agc Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_fpregs.c,v 1.14 2003/08/07 16:32:41 agc Exp $"); - -#include -#include -#include -#include -#include -#include -#include - -#include - -int -procfs_dofpregs(curp, l, pfs, uio) - struct proc *curp; /* tracer */ - struct lwp *l; /* traced */ - struct pfsnode *pfs; - struct uio *uio; -{ - - return (process_dofpregs(curp, l, uio)); -} - -int -procfs_validfpregs(p, mp) - struct proc *p; - struct mount *mp; -{ - - return (process_validfpregs(p)); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_linux.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_linux.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_linux.c 2006-10-24 18:04:12.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_linux.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,318 +0,0 @@ -/* $NetBSD: procfs_linux.c,v 1.22.2.1 2006/10/24 17:04:12 ghen Exp $ */ - -/* - * Copyright (c) 2001 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Frank van der Linden for Wasabi Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.22.2.1 2006/10/24 17:04:12 ghen Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define PGTOB(p) ((unsigned long)(p) << PAGE_SHIFT) -#define PGTOKB(p) ((unsigned long)(p) << (PAGE_SHIFT - 10)) - -/* - * Linux compatible /proc/meminfo. Only active when the -o linux - * mountflag is used. - */ -int -procfs_domeminfo(struct proc *curp, struct proc *p, struct pfsnode *pfs, - struct uio *uio) -{ - char buf[512]; - int len; - - len = snprintf(buf, sizeof buf, - " total: used: free: shared: buffers: cached:\n" - "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" - "Swap: %8lu %8lu %8lu\n" - "MemTotal: %8lu kB\n" - "MemFree: %8lu kB\n" - "MemShared: %8lu kB\n" - "Buffers: %8lu kB\n" - "Cached: %8lu kB\n" - "SwapTotal: %8lu kB\n" - "SwapFree: %8lu kB\n", - PGTOB(uvmexp.npages), - PGTOB(uvmexp.npages - uvmexp.free), - PGTOB(uvmexp.free), - 0L, - PGTOB(uvmexp.filepages), - PGTOB(uvmexp.anonpages + uvmexp.filepages + uvmexp.execpages), - PGTOB(uvmexp.swpages), - PGTOB(uvmexp.swpginuse), - PGTOB(uvmexp.swpages - uvmexp.swpginuse), - PGTOKB(uvmexp.npages), - PGTOKB(uvmexp.free), - 0L, - PGTOKB(uvmexp.filepages), - PGTOKB(uvmexp.anonpages + uvmexp.filepages + uvmexp.execpages), - PGTOKB(uvmexp.swpages), - PGTOKB(uvmexp.swpages - uvmexp.swpginuse)); - - if (len == 0) - return 0; - - return (uiomove_frombuf(buf, len, uio)); -} - -/* - * Linux compatible /proc//stat. Only active when the -o linux - * mountflag is used. - */ -int -procfs_do_pid_stat(struct proc *curp, struct lwp *l, struct pfsnode *pfs, - struct uio *uio) -{ - char buf[512]; - int len; - struct proc *p = l->l_proc; - struct tty *tty = p->p_session->s_ttyp; - struct rusage *ru = &p->p_stats->p_ru; - struct rusage *cru = &p->p_stats->p_cru; - struct vm_map *map = &p->p_vmspace->vm_map; - struct vm_map_entry *entry; - unsigned long stext = 0, etext = 0, sstack = 0; - - if (map != &curproc->p_vmspace->vm_map) - vm_map_lock_read(map); - for (entry = map->header.next; entry != &map->header; - entry = entry->next) { - if (UVM_ET_ISSUBMAP(entry)) - continue; - /* assume text is the first entry */ - if (stext == etext) { - stext = entry->start; - etext = entry->end; - break; - } - } -#ifdef LINUX_USRSTACK - if (strcmp(p->p_emul->e_name, "linux") == 0 && - LINUX_USRSTACK < USRSTACK) - sstack = (unsigned long) LINUX_USRSTACK; - else -#endif - sstack = (unsigned long) USRSTACK; - - if (map != &curproc->p_vmspace->vm_map) - vm_map_unlock_read(map); - - len = snprintf(buf, sizeof(buf), - "%d (%s) %c %d %d %d %d %d " - "%u " - "%lu %lu %lu %lu %lu %lu %lu %lu " - "%d %d %d " - "%lu %lu %lu %lu %" PRIu64 " " - "%lu %lu %lu " - "%u %u " - "%u %u %u %u " - "%lu %lu %lu %d %d\n", - - p->p_pid, - p->p_comm, - "0IR3SZD"[(p->p_stat > 6) ? 0 : (int)p->p_stat], - (p->p_pptr != NULL) ? p->p_pptr->p_pid : 0, - - p->p_pgid, - p->p_session->s_sid, - tty ? tty->t_dev : 0, - (tty && tty->t_pgrp) ? tty->t_pgrp->pg_id : 0, - - p->p_flag, - - ru->ru_minflt, - cru->ru_minflt, - ru->ru_majflt, - cru->ru_majflt, - ru->ru_utime.tv_sec, - ru->ru_stime.tv_sec, - cru->ru_utime.tv_sec, - cru->ru_stime.tv_sec, - - p->p_nice, /* XXX: priority */ - p->p_nice, - 0, - - p->p_rtime.tv_sec, - p->p_stats->p_start.tv_sec, - ru->ru_ixrss + ru->ru_idrss + ru->ru_isrss, - ru->ru_maxrss, - p->p_rlimit[RLIMIT_RSS].rlim_cur, - - stext, /* start code */ - etext, /* end code */ - sstack, /* mm start stack */ - 0, /* XXX: pc */ - 0, /* XXX: sp */ - p->p_sigctx.ps_siglist.__bits[0], /* pending */ - p->p_sigctx.ps_sigmask.__bits[0], /* blocked */ - p->p_sigctx.ps_sigignore.__bits[0], /* ignored */ - p->p_sigctx.ps_sigcatch.__bits[0], /* caught */ - - (unsigned long)(intptr_t)l->l_wchan, - ru->ru_nvcsw, - ru->ru_nivcsw, - p->p_exitsig, - 0); /* XXX: processor */ - - if (len == 0) - return 0; - - return (uiomove_frombuf(buf, len, uio)); -} - -int -procfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs, - struct uio *uio) -{ - int len = 4096; - char *buf = malloc(len, M_TEMP, M_WAITOK); - int error; - - if (procfs_getcpuinfstr(buf, &len) < 0) { - error = ENOSPC; - goto done; - } - - if (len == 0) { - error = 0; - goto done; - } - - error = uiomove_frombuf(buf, len, uio); -done: - free(buf, M_TEMP); - return error; -} - -int -procfs_douptime(struct proc *curp, struct proc *p, struct pfsnode *pfs, - struct uio *uio) -{ - char buf[512]; - int len; - struct timeval runtime; - u_int64_t idle; - - timersub(&curcpu()->ci_schedstate.spc_runtime, &boottime, &runtime); - idle = curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]; - len = snprintf(buf, sizeof(buf), - "%lu.%02lu %" PRIu64 ".%02" PRIu64 "\n", - runtime.tv_sec, runtime.tv_usec / 10000, - idle / hz, (((idle % hz) * 100) / hz) % 100); - - if (len == 0) - return 0; - - return (uiomove_frombuf(buf, len, uio)); -} - -int -procfs_domounts(struct proc *curp, struct proc *p, struct pfsnode *pfs, - struct uio *uio) -{ - char buf[512], *mtab = NULL; - const char *fsname; - size_t len, mtabsz = 0; - struct mount *mp, *nmp; - struct statvfs *sfs; - int error = 0; - - simple_lock(&mountlist_slock); - for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; - mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) { - nmp = CIRCLEQ_NEXT(mp, mnt_list); - continue; - } - - sfs = &mp->mnt_stat; - - /* Linux uses different names for some filesystems */ - fsname = sfs->f_fstypename; - if (strcmp(fsname, "procfs") == 0) - fsname = "proc"; - else if (strcmp(fsname, "ext2fs") == 0) - fsname = "ext2"; - - len = snprintf(buf, sizeof(buf), "%s %s %s %s%s%s%s%s%s 0 0\n", - sfs->f_mntfromname, - sfs->f_mntonname, - fsname, - (mp->mnt_flag & MNT_RDONLY) ? "ro" : "rw", - (mp->mnt_flag & MNT_NOSUID) ? ",nosuid" : "", - (mp->mnt_flag & MNT_NOEXEC) ? ",noexec" : "", - (mp->mnt_flag & MNT_NODEV) ? ",nodev" : "", - (mp->mnt_flag & MNT_SYNCHRONOUS) ? ",sync" : "", - (mp->mnt_flag & MNT_NOATIME) ? ",noatime" : "" - ); - - mtab = realloc(mtab, mtabsz + len, M_TEMP, M_WAITOK); - memcpy(mtab + mtabsz, buf, len); - mtabsz += len; - - simple_lock(&mountlist_slock); - nmp = CIRCLEQ_NEXT(mp, mnt_list); - vfs_unbusy(mp); - } - simple_unlock(&mountlist_slock); - - if (mtabsz > 0) { - error = uiomove_frombuf(mtab, mtabsz, uio); - free(mtab, M_TEMP); - } - - return error; -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_map.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_map.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_map.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_map.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,261 +0,0 @@ -/* $NetBSD: procfs_map.c,v 1.21 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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: procfs_map.c,v 1.18 1998/12/04 22:54:51 archie Exp $ - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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: procfs_map.c,v 1.18 1998/12/04 22:54:51 archie Exp $ - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_map.c,v 1.21 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#define MEBUFFERSIZE 256 - -extern int getcwd_common __P((struct vnode *, struct vnode *, - char **, char *, int, int, struct proc *)); - -static int procfs_vnode_to_path(struct vnode *vp, char *path, int len, - struct proc *curp, struct proc *p); - -/* - * 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(struct proc *curp, struct proc *p, struct pfsnode *pfs, - struct uio *uio, int linuxmode) -{ - size_t len; - int error; - struct vm_map *map = &p->p_vmspace->vm_map; - struct vm_map_entry *entry; - char mebuffer[MEBUFFERSIZE]; - char *path; - struct vnode *vp; - struct vattr va; - dev_t dev; - long fileid; - - 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) { - - if (UVM_ET_ISSUBMAP(entry)) - continue; - - if (linuxmode != 0) { - path = (char *)malloc(MAXPATHLEN * 4, M_TEMP, M_WAITOK); - if (path == NULL) { - error = ENOMEM; - break; - } - *path = 0; - - dev = (dev_t)0; - fileid = 0; - if (UVM_ET_ISOBJ(entry) && - UVM_OBJ_IS_VNODE(entry->object.uvm_obj)) { - vp = (struct vnode *)entry->object.uvm_obj; - error = VOP_GETATTR(vp, &va, curp->p_ucred, - curp); - if (error == 0 && vp != pfs->pfs_vnode) { - fileid = va.va_fileid; - dev = va.va_fsid; - error = procfs_vnode_to_path(vp, path, - MAXPATHLEN * 4, curp, p); - } - } - snprintf(mebuffer, sizeof(mebuffer), - "%0*lx-%0*lx %c%c%c%c %0*lx %02x:%02x %ld %s\n", - (int)sizeof(void *) * 2,(unsigned long)entry->start, - (int)sizeof(void *) * 2,(unsigned long)entry->end, - (entry->protection & VM_PROT_READ) ? 'r' : '-', - (entry->protection & VM_PROT_WRITE) ? 'w' : '-', - (entry->protection & VM_PROT_EXECUTE) ? 'x' : '-', - (entry->etype & UVM_ET_COPYONWRITE) ? 'p' : 's', - (int)sizeof(void *) * 2, - (unsigned long)entry->offset, - major(dev), minor(dev), fileid, path); - free(path, M_TEMP); - } else { - snprintf(mebuffer, sizeof(mebuffer), - "0x%lx 0x%lx %c%c%c %c%c%c %s %s %d %d %d\n", - entry->start, entry->end, - (entry->protection & VM_PROT_READ) ? 'r' : '-', - (entry->protection & VM_PROT_WRITE) ? 'w' : '-', - (entry->protection & VM_PROT_EXECUTE) ? 'x' : '-', - (entry->max_protection & VM_PROT_READ) ? 'r' : '-', - (entry->max_protection & VM_PROT_WRITE) ? 'w' : '-', - (entry->max_protection & VM_PROT_EXECUTE) ? - 'x' : '-', - (entry->etype & UVM_ET_COPYONWRITE) ? - "COW" : "NCOW", - (entry->etype & UVM_ET_NEEDSCOPY) ? "NC" : "NNC", - entry->inheritance, entry->wired_count, - entry->advice); - } - - 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(struct proc *p, struct mount *mp) -{ - return ((p->p_flag & P_SYSTEM) == 0); -} - -/* - * Try to find a pathname for a vnode. Since there is no mapping - * vnode -> parent directory, this needs the NAMECACHE_ENTER_REVERSE - * option to work (to make cache_revlookup succeed). - */ -static int procfs_vnode_to_path(struct vnode *vp, char *path, int len, - struct proc *curp, struct proc *p) -{ - int error, lenused, elen; - char *bp, *bend; - struct vnode *dvp; - - bp = bend = &path[len]; - *(--bp) = '\0'; - - error = vget(vp, LK_EXCLUSIVE | LK_RETRY); - if (error != 0) - return error; - error = cache_revlookup(vp, &dvp, &bp, path); - vput(vp); - if (error != 0) - return (error == -1 ? ENOENT : error); - - error = vget(dvp, 0); - if (error != 0) - return error; - *(--bp) = '/'; - /* XXX GETCWD_CHECK_ACCESS == 0x0001 */ - error = getcwd_common(dvp, NULL, &bp, path, len / 2, 1, curp); - - /* - * Strip off emulation path for emulated processes looking at - * the maps file of a process of the same emulation. (Won't - * work if /emul/xxx is a symlink..) - */ - if (curp->p_emul == p->p_emul && curp->p_emul->e_path != NULL) { - elen = strlen(curp->p_emul->e_path); - if (!strncmp(bp, curp->p_emul->e_path, elen)) - bp = &bp[elen]; - } - - lenused = bend - bp; - - memcpy(path, bp, lenused); - path[lenused] = 0; - - return 0; -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_mem.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_mem.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_mem.c 2003-08-07 17:32:41.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_mem.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,99 +0,0 @@ -/* $NetBSD: procfs_mem.c,v 1.34 2003/08/07 16:32:41 agc Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * Copyright (c) 1993 Sean Eric Fagan - * - * 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 - */ - -/* - * This is a lightly hacked and merged version - * of sef's pread/pwrite functions - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_mem.c,v 1.34 2003/08/07 16:32:41 agc Exp $"); - -#include -#include -#include -#include - -#include - -int -procfs_domem(curp, p, pfs, uio) - struct proc *curp; /* tracer */ - struct proc *p; /* traced */ - struct pfsnode *pfs; - struct uio *uio; -{ - - return (process_domem(curp, p, uio)); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_note.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_note.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_note.c 2003-08-07 17:32:42.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_note.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,107 +0,0 @@ -/* $NetBSD: procfs_note.c,v 1.12 2003/08/07 16:32:42 agc Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_note.c,v 1.12 2003/08/07 16:32:42 agc Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include - -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 -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_regs.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_regs.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_regs.c 2003-08-07 17:32:42.000000000 +0100 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_regs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,102 +0,0 @@ -/* $NetBSD: procfs_regs.c,v 1.20 2003/08/07 16:32:42 agc Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_regs.c,v 1.20 2003/08/07 16:32:42 agc Exp $"); - -#include -#include -#include -#include - -#include - -int -procfs_doregs(curp, l, pfs, uio) - struct proc *curp; /* tracer */ - struct lwp *l; /* traced */ - struct pfsnode *pfs; - struct uio *uio; -{ - - return (process_doregs(curp, l, uio)); -} - -int -procfs_validregs(p, mp) - struct proc *p; - struct mount *mp; -{ - - return (process_validregs(p)); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_status.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_status.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_status.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_status.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,171 +0,0 @@ -/* $NetBSD: procfs_status.c,v 1.24 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_status.c,v 1.24 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -procfs_dostatus(curp, l, pfs, uio) - struct proc *curp; - struct lwp *l; - struct pfsnode *pfs; - struct uio *uio; -{ - struct session *sess; - struct tty *tp; - struct ucred *cr; - struct proc *p = l->l_proc; - char *ps; - char *sep; - int pid, ppid, pgid, sid; - u_int i; - char psbuf[256+MAXHOSTNAMELEN]; /* XXX - conservative */ - - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - pid = p->p_pid; - ppid = p->p_pptr ? p->p_pptr->p_pid : 0, - pgid = p->p_pgrp->pg_id; - sess = p->p_pgrp->pg_session; - sid = sess->s_sid; - -/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg uid gid groups ... */ - - ps = psbuf; - memcpy(ps, p->p_comm, MAXCOMLEN); - ps[MAXCOMLEN] = '\0'; - ps += strlen(ps); - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " %d %d %d %d ", - pid, ppid, pgid, sid); - - if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp)) - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "%d,%d ", - major(tp->t_dev), minor(tp->t_dev)); - else - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "%d,%d ", - -1, -1); - - sep = ""; - if (sess->s_ttyvp) { - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "%sctty", sep); - sep = ","; - } - if (SESS_LEADER(p)) { - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "%ssldr", sep); - sep = ","; - } - if (*sep != ',') - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "noflags"); - - if (l->l_flag & L_INMEM) - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " %ld,%ld", - p->p_stats->p_start.tv_sec, p->p_stats->p_start.tv_usec); - else - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " -1,-1"); - - { - struct timeval ut, st; - - calcru(p, &ut, &st, (void *) 0); - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), - " %ld,%ld %ld,%ld", ut.tv_sec, ut.tv_usec, st.tv_sec, - st.tv_usec); - } - - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " %s", - (l->l_wchan && l->l_wmesg) ? l->l_wmesg : "nochan"); - - cr = p->p_ucred; - - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " %d", cr->cr_uid); - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), " %d", cr->cr_gid); - for (i = 0; i < cr->cr_ngroups; i++) - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), ",%d", - cr->cr_groups[i]); - ps += snprintf(ps, sizeof(psbuf) - (ps - psbuf), "\n"); - - return (uiomove_frombuf(psbuf, ps - psbuf, uio)); -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_subr.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_subr.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_subr.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_subr.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,588 +0,0 @@ -/* $NetBSD: procfs_subr.c,v 1.63 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.63 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -void procfs_hashins __P((struct pfsnode *)); -void procfs_hashrem __P((struct pfsnode *)); -struct vnode *procfs_hashget __P((pid_t, pfstype, int, struct mount *)); - -LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl; -u_long pfs_ihash; /* size of hash table - 1 */ -#define PFSPIDHASH(pid) ((pid) & pfs_ihash) - -struct lock pfs_hashlock; -struct simplelock pfs_hash_slock; - -#define ISSET(t, f) ((t) & (f)) - -/* - * allocate a pfsnode/vnode pair. the vnode is - * referenced, and 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, fd) - struct mount *mp; - struct vnode **vpp; - pid_t pid; - pfstype pfs_type; - int fd; -{ - struct pfsnode *pfs; - struct vnode *vp; - int error; - - do { - if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp)) != NULL) - return (0); - } while (lockmgr(&pfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0)); - - if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp)) != 0) { - *vpp = NULL; - lockmgr(&pfs_hashlock, LK_RELEASE, NULL); - return (error); - } - - MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); - vp->v_data = pfs; - - pfs->pfs_pid = pid; - pfs->pfs_type = pfs_type; - pfs->pfs_vnode = vp; - pfs->pfs_flags = 0; - pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd); - pfs->pfs_fd = fd; - - switch (pfs_type) { - case PFSroot: /* /proc = dr-xr-xr-x */ - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VDIR; - vp->v_flag = VROOT; - break; - - case PFScurproc: /* /proc/curproc = lr-xr-xr-x */ - case PFSself: /* /proc/self = lr-xr-xr-x */ - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VLNK; - break; - - case PFSproc: /* /proc/N = dr-xr-xr-x */ - case PFSfd: - if (fd == -1) { /* /proc/N/fd = dr-xr-xr-x */ - pfs->pfs_mode = S_IRUSR|S_IXUSR; - vp->v_type = VDIR; - } else { /* /proc/N/fd/M = [ps-]rw------- */ - struct file *fp; - struct vnode *vxp; - struct proc *pown; - - /* XXX can procfs_getfp() ever fail here? */ - if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) - goto bad; - FILE_USE(fp); - - pfs->pfs_mode = S_IRUSR|S_IWUSR; - switch (fp->f_type) { - case DTYPE_VNODE: - vxp = (struct vnode *)fp->f_data; - - /* - * We make symlinks for directories - * to avoid cycles. - */ - if (vxp->v_type == VDIR) - goto symlink; - vp->v_type = vxp->v_type; - break; - case DTYPE_PIPE: - vp->v_type = VFIFO; - break; - case DTYPE_SOCKET: - vp->v_type = VSOCK; - break; - case DTYPE_KQUEUE: - case DTYPE_MISC: - symlink: - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP| - S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VLNK; - break; - default: - error = EOPNOTSUPP; - FILE_UNUSE(fp, pown); - goto bad; - } - FILE_UNUSE(fp, pown); - } - break; - - case PFSfile: /* /proc/N/file = -rw------- */ - case PFSmem: /* /proc/N/mem = -rw------- */ - case PFSregs: /* /proc/N/regs = -rw------- */ - case PFSfpregs: /* /proc/N/fpregs = -rw------- */ - pfs->pfs_mode = S_IRUSR|S_IWUSR; - vp->v_type = VREG; - break; - - case PFSctl: /* /proc/N/ctl = --w------ */ - case PFSnote: /* /proc/N/note = --w------ */ - case PFSnotepg: /* /proc/N/notepg = --w------ */ - pfs->pfs_mode = S_IWUSR; - vp->v_type = VREG; - break; - - case PFSmap: /* /proc/N/map = -r--r--r-- */ - case PFSmaps: /* /proc/N/maps = -r--r--r-- */ - case PFSstatus: /* /proc/N/status = -r--r--r-- */ - case PFSstat: /* /proc/N/stat = -r--r--r-- */ - case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */ - case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */ - case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */ - case PFSuptime: /* /proc/uptime = -r--r--r-- */ - case PFSmounts: /* /proc/mounts = -r--r--r-- */ - pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; - vp->v_type = VREG; - break; - -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODETYPE_CASES - procfs_machdep_allocvp(vp); - break; -#endif - - default: - panic("procfs_allocvp"); - } - - procfs_hashins(pfs); - uvm_vnp_setsize(vp, 0); - lockmgr(&pfs_hashlock, LK_RELEASE, NULL); - - *vpp = vp; - return (0); - - bad: - lockmgr(&pfs_hashlock, LK_RELEASE, NULL); - FREE(pfs, M_TEMP); - ungetnewvnode(vp); - return (error); -} - -int -procfs_freevp(vp) - struct vnode *vp; -{ - struct pfsnode *pfs = VTOPFS(vp); - - procfs_hashrem(pfs); - - FREE(vp->v_data, M_TEMP); - vp->v_data = 0; - return (0); -} - -int -procfs_rw(v) - void *v; -{ - struct vop_read_args *ap = v; - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - struct proc *curp = uio->uio_procp; - struct pfsnode *pfs = VTOPFS(vp); - struct lwp *l; - struct proc *p; - - if (uio->uio_offset < 0) - return EINVAL; - p = PFIND(pfs->pfs_pid); - if (p == 0) - return ESRCH; - /* - * Do not allow init to be modified while in secure mode; it - * could be duped into changing the security level. - */ - if (uio->uio_rw == UIO_WRITE && p == initproc && securelevel > -1) - return EPERM; - - /* XXX NJWLWP - * The entire procfs interface needs work to be useful to - * a process with multiple LWPs. For the moment, we'll - * just kluge this and fail on others. - */ - l = proc_representative_lwp(p); - - switch (pfs->pfs_type) { - case PFSnote: - case PFSnotepg: - return (procfs_donote(curp, p, pfs, uio)); - - case PFSregs: - return (procfs_doregs(curp, l, pfs, uio)); - - case PFSfpregs: - return (procfs_dofpregs(curp, l, pfs, uio)); - - case PFSctl: - return (procfs_doctl(curp, l, pfs, uio)); - - case PFSstatus: - return (procfs_dostatus(curp, l, pfs, uio)); - - case PFSstat: - return (procfs_do_pid_stat(curp, l, pfs, uio)); - - case PFSmap: - return (procfs_domap(curp, p, pfs, uio, 0)); - - case PFSmaps: - return (procfs_domap(curp, p, pfs, uio, 1)); - - case PFSmem: - return (procfs_domem(curp, p, pfs, uio)); - - case PFScmdline: - return (procfs_docmdline(curp, p, pfs, uio)); - - case PFSmeminfo: - return (procfs_domeminfo(curp, p, pfs, uio)); - - case PFScpuinfo: - return (procfs_docpuinfo(curp, p, pfs, uio)); - - case PFSfd: - return (procfs_dofd(curp, p, pfs, uio)); - - case PFSuptime: - return (procfs_douptime(curp, p, pfs, uio)); - - case PFSmounts: - return (procfs_domounts(curp, p, pfs, uio)); - -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODETYPE_CASES - return (procfs_machdep_rw(curp, l, pfs, uio)); -#endif - - default: - return (EOPNOTSUPP); - } -} - -/* - * 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); -} - -const vfs_namemap_t * -vfs_findname(nm, buf, buflen) - const vfs_namemap_t *nm; - const char *buf; - int buflen; -{ - - for (; nm->nm_name; nm++) - if (memcmp(buf, nm->nm_name, buflen+1) == 0) - return (nm); - - return (0); -} - -/* - * Initialize pfsnode hash table. - */ -void -procfs_hashinit() -{ - lockinit(&pfs_hashlock, PINOD, "pfs_hashlock", 0, 0); - pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, - M_WAITOK, &pfs_ihash); - simple_lock_init(&pfs_hash_slock); -} - -void -procfs_hashreinit() -{ - struct pfsnode *pp; - struct pfs_hashhead *oldhash, *hash; - u_long i, oldmask, mask, val; - - hash = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, M_WAITOK, - &mask); - - simple_lock(&pfs_hash_slock); - oldhash = pfs_hashtbl; - oldmask = pfs_ihash; - pfs_hashtbl = hash; - pfs_ihash = mask; - for (i = 0; i <= oldmask; i++) { - while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { - LIST_REMOVE(pp, pfs_hash); - val = PFSPIDHASH(pp->pfs_pid); - LIST_INSERT_HEAD(&hash[val], pp, pfs_hash); - } - } - simple_unlock(&pfs_hash_slock); - hashdone(oldhash, M_UFSMNT); -} - -/* - * Free pfsnode hash table. - */ -void -procfs_hashdone() -{ - hashdone(pfs_hashtbl, M_UFSMNT); -} - -struct vnode * -procfs_hashget(pid, type, fd, mp) - pid_t pid; - pfstype type; - int fd; - struct mount *mp; -{ - struct pfs_hashhead *ppp; - struct pfsnode *pp; - struct vnode *vp; - -loop: - simple_lock(&pfs_hash_slock); - ppp = &pfs_hashtbl[PFSPIDHASH(pid)]; - LIST_FOREACH(pp, ppp, pfs_hash) { - vp = PFSTOV(pp); - if (pid == pp->pfs_pid && pp->pfs_type == type && - pp->pfs_fd == fd && vp->v_mount == mp) { - simple_lock(&vp->v_interlock); - simple_unlock(&pfs_hash_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) - goto loop; - return (vp); - } - } - simple_unlock(&pfs_hash_slock); - return (NULL); -} - -/* - * Insert the pfsnode into the hash table and lock it. - */ -void -procfs_hashins(pp) - struct pfsnode *pp; -{ - struct pfs_hashhead *ppp; - - /* lock the pfsnode, then put it on the appropriate hash list */ - lockmgr(&pp->pfs_vnode->v_lock, LK_EXCLUSIVE, (struct simplelock *)0); - - simple_lock(&pfs_hash_slock); - ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)]; - LIST_INSERT_HEAD(ppp, pp, pfs_hash); - simple_unlock(&pfs_hash_slock); -} - -/* - * Remove the pfsnode from the hash table. - */ -void -procfs_hashrem(pp) - struct pfsnode *pp; -{ - simple_lock(&pfs_hash_slock); - LIST_REMOVE(pp, pfs_hash); - simple_unlock(&pfs_hash_slock); -} - -void -procfs_revoke_vnodes(p, arg) - struct proc *p; - void *arg; -{ - struct pfsnode *pfs, *pnext; - struct vnode *vp; - struct mount *mp = (struct mount *)arg; - struct pfs_hashhead *ppp; - - if (!(p->p_flag & P_SUGID)) - return; - - ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)]; - for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) { - vp = PFSTOV(pfs); - pnext = LIST_NEXT(pfs, pfs_hash); - if (vp->v_usecount > 0 && pfs->pfs_pid == p->p_pid && - vp->v_mount == mp) - VOP_REVOKE(vp, REVOKEALL); - } -} - -int -procfs_getfp(pfs, pown, fp) - struct pfsnode *pfs; - struct proc **pown; - struct file **fp; -{ - struct proc *p = PFIND(pfs->pfs_pid); - - if (p == NULL) - return ESRCH; - - if (pfs->pfs_fd == -1) - return EINVAL; - - if ((*fp = fd_getfile(p->p_fd, pfs->pfs_fd)) == NULL) - return EBADF; - - *pown = p; - return 0; -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_vfsops.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_vfsops.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_vfsops.c 2005-01-02 16:08:30.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_vfsops.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,387 +0,0 @@ -/* $NetBSD: procfs_vfsops.c,v 1.59 2005/01/02 16:08:30 thorpej Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -/* - * procfs VFS interface - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.59 2005/01/02 16:08:30 thorpej Exp $"); - -#if defined(_KERNEL_OPT) -#include "opt_compat_netbsd.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include /* for PAGE_SIZE */ - -void procfs_init __P((void)); -void procfs_reinit __P((void)); -void procfs_done __P((void)); -int procfs_mount __P((struct mount *, const char *, void *, - struct nameidata *, struct proc *)); -int procfs_start __P((struct mount *, int, struct proc *)); -int procfs_unmount __P((struct mount *, int, struct proc *)); -int procfs_quotactl __P((struct mount *, int, uid_t, void *, - struct proc *)); -int procfs_statvfs __P((struct mount *, struct statvfs *, struct proc *)); -int procfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); -int procfs_vget __P((struct mount *, ino_t, struct vnode **)); -int procfs_fhtovp __P((struct mount *, struct fid *, struct vnode **)); -int procfs_checkexp __P((struct mount *, struct mbuf *, int *, - struct ucred **)); -int procfs_vptofh __P((struct vnode *, struct fid *)); - -/* - * VFS Operations. - * - * mount system call - */ -/* ARGSUSED */ -int -procfs_mount(mp, path, data, ndp, p) - struct mount *mp; - const char *path; - void *data; - struct nameidata *ndp; - struct proc *p; -{ - struct procfsmount *pmnt; - struct procfs_args args; - int error; - - if (UIO_MX & (UIO_MX-1)) { - log(LOG_ERR, "procfs: invalid directory entry size"); - return (EINVAL); - } - - if (mp->mnt_flag & MNT_GETARGS) { - pmnt = VFSTOPROC(mp); - if (pmnt == NULL) - return EIO; - args.version = PROCFS_ARGSVERSION; - args.flags = pmnt->pmnt_flags; - return copyout(&args, data, sizeof(args)); - } - - if (mp->mnt_flag & MNT_UPDATE) - return (EOPNOTSUPP); - - if (data != NULL) { - error = copyin(data, &args, sizeof args); - if (error != 0) - return error; - - if (args.version != PROCFS_ARGSVERSION) - return EINVAL; - } else - args.flags = 0; - - pmnt = (struct procfsmount *) malloc(sizeof(struct procfsmount), - M_UFSMNT, M_WAITOK); /* XXX need new malloc type */ - - mp->mnt_stat.f_namemax = MAXNAMLEN; - mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = pmnt; - vfs_getnewfsid(mp); - - error = set_statvfs_info(path, UIO_USERSPACE, "procfs", UIO_SYSSPACE, - mp, p); - pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp); - pmnt->pmnt_flags = args.flags; - - return error; -} - -/* - * unmount system call - */ -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; - - if ((error = vflush(mp, 0, flags)) != 0) - return (error); - - exechook_disestablish(VFSTOPROC(mp)->pmnt_exechook); - - free(mp->mnt_data, M_UFSMNT); - mp->mnt_data = 0; - - return (0); -} - -int -procfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - - return (procfs_allocvp(mp, vpp, 0, PFSroot, -1)); -} - -/* ARGSUSED */ -int -procfs_start(mp, flags, p) - struct mount *mp; - int flags; - struct proc *p; -{ - - return (0); -} - -/* - * Get file system statistics. - */ -int -procfs_statvfs(mp, sbp, p) - struct mount *mp; - struct statvfs *sbp; - struct proc *p; -{ - - sbp->f_bsize = PAGE_SIZE; - sbp->f_frsize = 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_bresvd = 0; - sbp->f_files = maxproc; /* approx */ - sbp->f_ffree = maxproc - nprocs; /* approx */ - sbp->f_favail = maxproc - nprocs; /* approx */ - sbp->f_fresvd = 0; - copy_statvfs_info(sbp, mp); - return (0); -} - -/*ARGSUSED*/ -int -procfs_quotactl(mp, cmds, uid, arg, p) - struct mount *mp; - int cmds; - uid_t uid; - void *arg; - struct proc *p; -{ - - return (EOPNOTSUPP); -} - -/*ARGSUSED*/ -int -procfs_sync(mp, waitfor, uc, p) - struct mount *mp; - int waitfor; - struct ucred *uc; - struct proc *p; -{ - - return (0); -} - -/*ARGSUSED*/ -int -procfs_vget(mp, ino, vpp) - struct mount *mp; - ino_t ino; - struct vnode **vpp; -{ - return (EOPNOTSUPP); -} - -/*ARGSUSED*/ -int -procfs_fhtovp(mp, fhp, vpp) - struct mount *mp; - struct fid *fhp; - struct vnode **vpp; -{ - - return (EINVAL); -} - -/*ARGSUSED*/ -int -procfs_checkexp(mp, mb, what, anon) - struct mount *mp; - struct mbuf *mb; - int *what; - struct ucred **anon; -{ - - return (EINVAL); -} - -/*ARGSUSED*/ -int -procfs_vptofh(vp, fhp) - struct vnode *vp; - struct fid *fhp; -{ - - return (EINVAL); -} - -void -procfs_init() -{ - procfs_hashinit(); -} - -void -procfs_reinit() -{ - procfs_hashreinit(); -} - -void -procfs_done() -{ - procfs_hashdone(); -} - -SYSCTL_SETUP(sysctl_vfs_procfs_setup, "sysctl vfs.procfs subtree setup") -{ - - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "vfs", NULL, - NULL, 0, NULL, 0, - CTL_VFS, CTL_EOL); - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "procfs", - SYSCTL_DESCR("Process file system"), - NULL, 0, NULL, 0, - CTL_VFS, 12, CTL_EOL); - /* - * XXX the "12" above could be dynamic, thereby eliminating - * one more instance of the "number to vfs" mapping problem, - * but "12" is the order as taken from sys/mount.h - */ -} - -extern const struct vnodeopv_desc procfs_vnodeop_opv_desc; - -const struct vnodeopv_desc * const procfs_vnodeopv_descs[] = { - &procfs_vnodeop_opv_desc, - NULL, -}; - -struct vfsops procfs_vfsops = { - MOUNT_PROCFS, - procfs_mount, - procfs_start, - procfs_unmount, - procfs_root, - procfs_quotactl, - procfs_statvfs, - procfs_sync, - procfs_vget, - procfs_fhtovp, - procfs_vptofh, - procfs_init, - procfs_reinit, - procfs_done, - NULL, - NULL, /* vfs_mountroot */ - procfs_checkexp, - (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp, - vfs_stdextattrctl, - procfs_vnodeopv_descs, -}; diff -r -u -N --exclude CVS NetBSD-3.1/sys/miscfs/procfs/procfs_vnops.c mult-netbsd-3.1/sys/miscfs/procfs/procfs_vnops.c --- NetBSD-3.1/sys/miscfs/procfs/procfs_vnops.c 2005-02-26 22:59:00.000000000 +0000 +++ mult-netbsd-3.1/sys/miscfs/procfs/procfs_vnops.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1410 +0,0 @@ -/* $NetBSD: procfs_vnops.c,v 1.121 2005/02/26 22:59:00 perry Exp $ */ - -/* - * 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. 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 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * 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 - */ - -/* - * procfs vnode interface - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.121 2005/02/26 22:59:00 perry Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* for PAGE_SIZE */ - -#include - -#include -#include - -/* - * Vnode Operations. - * - */ - -static int procfs_validfile_linux __P((struct proc *, struct mount *)); -static int procfs_root_readdir_callback(struct proc *, void *); - -/* - * This is a list of the valid names in the - * process-specific sub-directories. It is - * used in procfs_lookup and procfs_readdir - */ -static const struct proc_target { - u_char pt_type; - u_char pt_namlen; - const char *pt_name; - pfstype pt_pfstype; - int (*pt_valid) __P((struct proc *, struct mount *)); -} proc_targets[] = { -#define N(s) sizeof(s)-1, s - /* name type validp */ - { DT_DIR, N("."), PFSproc, NULL }, - { DT_DIR, N(".."), PFSroot, NULL }, - { DT_DIR, N("fd"), PFSfd, NULL }, - { DT_REG, N("file"), PFSfile, procfs_validfile }, - { DT_REG, N("mem"), PFSmem, NULL }, - { DT_REG, N("regs"), PFSregs, procfs_validregs }, - { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs }, - { DT_REG, N("ctl"), PFSctl, NULL }, - { DT_REG, N("stat"), PFSstat, procfs_validfile_linux }, - { DT_REG, N("status"), PFSstatus, NULL }, - { DT_REG, N("note"), PFSnote, NULL }, - { DT_REG, N("notepg"), PFSnotepg, NULL }, - { DT_REG, N("map"), PFSmap, procfs_validmap }, - { DT_REG, N("maps"), PFSmaps, procfs_validmap }, - { DT_REG, N("cmdline"), PFScmdline, NULL }, - { DT_REG, N("exe"), PFSfile, procfs_validfile_linux }, -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODETYPE_DEFNS -#endif -#undef N -}; -static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); - -/* - * List of files in the root directory. Note: the validate function will - * be called with p == NULL for these ones. - */ -static const struct proc_target proc_root_targets[] = { -#define N(s) sizeof(s)-1, s - /* name type validp */ - { DT_REG, N("meminfo"), PFSmeminfo, procfs_validfile_linux }, - { DT_REG, N("cpuinfo"), PFScpuinfo, procfs_validfile_linux }, - { DT_REG, N("uptime"), PFSuptime, procfs_validfile_linux }, - { DT_REG, N("mounts"), PFSmounts, procfs_validfile_linux }, -#undef N -}; -static const int nproc_root_targets = - sizeof(proc_root_targets) / sizeof(proc_root_targets[0]); - -int procfs_lookup __P((void *)); -#define procfs_create genfs_eopnotsupp -#define procfs_mknod genfs_eopnotsupp -int procfs_open __P((void *)); -int procfs_close __P((void *)); -int procfs_access __P((void *)); -int procfs_getattr __P((void *)); -int procfs_setattr __P((void *)); -#define procfs_read procfs_rw -#define procfs_write procfs_rw -#define procfs_fcntl genfs_fcntl -#define procfs_ioctl genfs_enoioctl -#define procfs_poll genfs_poll -#define procfs_revoke genfs_revoke -#define procfs_fsync genfs_nullop -#define procfs_seek genfs_nullop -#define procfs_remove genfs_eopnotsupp -int procfs_link __P((void *)); -#define procfs_rename genfs_eopnotsupp -#define procfs_mkdir genfs_eopnotsupp -#define procfs_rmdir genfs_eopnotsupp -int procfs_symlink __P((void *)); -int procfs_readdir __P((void *)); -int procfs_readlink __P((void *)); -#define procfs_abortop genfs_abortop -int procfs_inactive __P((void *)); -int procfs_reclaim __P((void *)); -#define procfs_lock genfs_lock -#define procfs_unlock genfs_unlock -#define procfs_bmap genfs_badop -#define procfs_strategy genfs_badop -int procfs_print __P((void *)); -int procfs_pathconf __P((void *)); -#define procfs_islocked genfs_islocked -#define procfs_advlock genfs_einval -#define procfs_blkatoff genfs_eopnotsupp -#define procfs_valloc genfs_eopnotsupp -#define procfs_vfree genfs_nullop -#define procfs_truncate genfs_eopnotsupp -#define procfs_update genfs_nullop -#define procfs_bwrite genfs_eopnotsupp -#define procfs_putpages genfs_null_putpages - -static int atoi __P((const char *, size_t)); - -/* - * procfs vnode operations. - */ -int (**procfs_vnodeop_p) __P((void *)); -const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = { - { &vop_default_desc, vn_default_error }, - { &vop_lookup_desc, procfs_lookup }, /* lookup */ - { &vop_create_desc, procfs_create }, /* create */ - { &vop_mknod_desc, procfs_mknod }, /* mknod */ - { &vop_open_desc, procfs_open }, /* open */ - { &vop_close_desc, procfs_close }, /* close */ - { &vop_access_desc, procfs_access }, /* access */ - { &vop_getattr_desc, procfs_getattr }, /* getattr */ - { &vop_setattr_desc, procfs_setattr }, /* setattr */ - { &vop_read_desc, procfs_read }, /* read */ - { &vop_write_desc, procfs_write }, /* write */ - { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */ - { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ - { &vop_poll_desc, procfs_poll }, /* poll */ - { &vop_revoke_desc, procfs_revoke }, /* revoke */ - { &vop_fsync_desc, procfs_fsync }, /* fsync */ - { &vop_seek_desc, procfs_seek }, /* seek */ - { &vop_remove_desc, procfs_remove }, /* remove */ - { &vop_link_desc, procfs_link }, /* link */ - { &vop_rename_desc, procfs_rename }, /* rename */ - { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */ - { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */ - { &vop_symlink_desc, procfs_symlink }, /* symlink */ - { &vop_readdir_desc, procfs_readdir }, /* readdir */ - { &vop_readlink_desc, procfs_readlink }, /* readlink */ - { &vop_abortop_desc, procfs_abortop }, /* abortop */ - { &vop_inactive_desc, procfs_inactive }, /* inactive */ - { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */ - { &vop_lock_desc, procfs_lock }, /* lock */ - { &vop_unlock_desc, procfs_unlock }, /* unlock */ - { &vop_bmap_desc, procfs_bmap }, /* bmap */ - { &vop_strategy_desc, procfs_strategy }, /* strategy */ - { &vop_print_desc, procfs_print }, /* print */ - { &vop_islocked_desc, procfs_islocked }, /* islocked */ - { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */ - { &vop_advlock_desc, procfs_advlock }, /* advlock */ - { &vop_blkatoff_desc, procfs_blkatoff }, /* blkatoff */ - { &vop_valloc_desc, procfs_valloc }, /* valloc */ - { &vop_vfree_desc, procfs_vfree }, /* vfree */ - { &vop_truncate_desc, procfs_truncate }, /* truncate */ - { &vop_update_desc, procfs_update }, /* update */ - { &vop_putpages_desc, procfs_putpages }, /* putpages */ - { NULL, NULL } -}; -const struct vnodeopv_desc procfs_vnodeop_opv_desc = - { &procfs_vnodeop_p, procfs_vnodeop_entries }; -/* - * 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. - */ -int -procfs_open(v) - void *v; -{ - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *p1, *p2; - int error; - - p1 = ap->a_p; /* tracer */ - p2 = PFIND(pfs->pfs_pid); /* traced */ - - if (p2 == NULL) - return (ENOENT); /* was ESRCH, jsp */ - - switch (pfs->pfs_type) { - case PFSmem: - if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || - ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) - return (EBUSY); - - if ((error = process_checkioperm(p1, p2)) != 0) - return (error); - - if (ap->a_mode & FWRITE) - pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); - - return (0); - - default: - break; - } - - return (0); -} - -/* - * 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). - */ -int -procfs_close(v) - void *v; -{ - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - - switch (pfs->pfs_type) { - case PFSmem: - if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) - pfs->pfs_flags &= ~(FWRITE|O_EXCL); - break; - - default: - break; - } - - return (0); -} - -/* - * _inactive is called when the pfsnode - * is vrele'd and the reference count goes - * to zero. (vp) will be on the vnode free - * list, so to get it back vget() must be - * used. - * - * for procfs, check if the process is still - * alive and if it isn't then just throw away - * the vnode by calling vgone(). this may - * be overkill and a waste of time since the - * chances are that the process will still be - * there and PFIND is not free. - * - * (vp) is locked on entry, but must be unlocked on exit. - */ -int -procfs_inactive(v) - void *v; -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - - VOP_UNLOCK(ap->a_vp, 0); - if (PFIND(pfs->pfs_pid) == NULL) - vgone(ap->a_vp); - - 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. - */ -int -procfs_reclaim(v) - void *v; -{ - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap = v; - - return (procfs_freevp(ap->a_vp)); -} - -/* - * Return POSIX pathconf information applicable to special devices. - */ -int -procfs_pathconf(v) - void *v; -{ - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - register_t *a_retval; - } */ *ap = v; - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = LINK_MAX; - return (0); - case _PC_MAX_CANON: - *ap->a_retval = MAX_CANON; - return (0); - case _PC_MAX_INPUT: - *ap->a_retval = MAX_INPUT; - return (0); - case _PC_PIPE_BUF: - *ap->a_retval = PIPE_BUF; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_VDISABLE: - *ap->a_retval = _POSIX_VDISABLE; - return (0); - case _PC_SYNC_IO: - *ap->a_retval = 1; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -/* - * _print is used for debugging. - * just print a readable description - * of (vp). - */ -int -procfs_print(v) - void *v; -{ - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap = v; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - - printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", - pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); - return 0; -} - -int -procfs_link(v) - void *v; -{ - struct vop_link_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EROFS); -} - -int -procfs_symlink(v) - void *v; -{ - struct vop_symlink_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - char *a_target; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EROFS); -} - -/* - * 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. - */ -int -procfs_getattr(v) - void *v; -{ - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct vattr *vap = ap->a_vap; - struct proc *procp; - int error; - - /* first check the process still exists */ - switch (pfs->pfs_type) { - case PFSroot: - case PFScurproc: - case PFSself: - procp = 0; - break; - - default: - procp = PFIND(pfs->pfs_pid); - if (procp == NULL) - return (ENOENT); - break; - } - - 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; - - /* - * Make all times be current TOD. Avoid microtime(9), it's slow. - * We don't guard the read from time(9) with splclock(9) since we - * don't actually need to be THAT sure the access is atomic. - * - * 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. - */ - TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime); - vap->va_atime = vap->va_mtime = vap->va_ctime; - - switch (pfs->pfs_type) { - case PFSmem: - case PFSregs: - case PFSfpregs: -#if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES) - PROCFS_MACHDEP_PROTECT_CASES -#endif - /* - * If the process has exercised some setuid or setgid - * privilege, then rip away read/write permission so - * that only root can gain access. - */ - if (procp->p_flag & P_SUGID) - vap->va_mode &= ~(S_IRUSR|S_IWUSR); - /* FALLTHROUGH */ - case PFSctl: - case PFSstatus: - case PFSstat: - case PFSnote: - case PFSnotepg: - case PFSmap: - case PFSmaps: - case PFScmdline: - vap->va_nlink = 1; - vap->va_uid = procp->p_ucred->cr_uid; - vap->va_gid = procp->p_ucred->cr_gid; - break; - case PFSmeminfo: - case PFScpuinfo: - case PFSuptime: - case PFSmounts: - vap->va_nlink = 1; - vap->va_uid = vap->va_gid = 0; - 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. - */ - - switch (pfs->pfs_type) { - case PFSroot: - /* - * 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_bytes = vap->va_size = DEV_BSIZE; - break; - - case PFScurproc: { - char buf[16]; /* should be enough */ - vap->va_nlink = 1; - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_bytes = vap->va_size = - snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - break; - } - - case PFSself: - vap->va_nlink = 1; - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_bytes = vap->va_size = sizeof("curproc") - 1; - break; - - case PFSfd: - if (pfs->pfs_fd != -1) { - struct file *fp; - struct proc *pown; - - if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) - return error; - FILE_USE(fp); - vap->va_nlink = 1; - vap->va_uid = fp->f_cred->cr_uid; - vap->va_gid = fp->f_cred->cr_gid; - switch (fp->f_type) { - case DTYPE_VNODE: - vap->va_bytes = vap->va_size = - ((struct vnode *)fp->f_data)->v_size; - break; - default: - vap->va_bytes = vap->va_size = 0; - break; - } - FILE_UNUSE(fp, pown); - break; - } - /*FALLTHROUGH*/ - case PFSproc: - vap->va_nlink = 2; - vap->va_uid = procp->p_ucred->cr_uid; - vap->va_gid = procp->p_ucred->cr_gid; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; - - case PFSfile: - error = EOPNOTSUPP; - break; - - case PFSmem: - vap->va_bytes = vap->va_size = - ctob(procp->p_vmspace->vm_tsize + - procp->p_vmspace->vm_dsize + - procp->p_vmspace->vm_ssize); - break; - -#if defined(PT_GETREGS) || defined(PT_SETREGS) - case PFSregs: - vap->va_bytes = vap->va_size = sizeof(struct reg); - break; -#endif - -#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) - case PFSfpregs: - vap->va_bytes = vap->va_size = sizeof(struct fpreg); - break; -#endif - - case PFSctl: - case PFSstatus: - case PFSstat: - case PFSnote: - case PFSnotepg: - case PFScmdline: - case PFSmeminfo: - case PFScpuinfo: - case PFSuptime: - case PFSmounts: - vap->va_bytes = vap->va_size = 0; - break; - case PFSmap: - case PFSmaps: - /* - * Advise a larger blocksize for the map files, so that - * they may be read in one pass. - */ - vap->va_blocksize = 4 * PAGE_SIZE; - vap->va_bytes = vap->va_size = 0; - break; - -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODETYPE_CASES - error = procfs_machdep_getattr(ap->a_vp, vap, procp); - break; -#endif - - default: - panic("procfs_getattr"); - } - - return (error); -} - -/*ARGSUSED*/ -int -procfs_setattr(v) - void *v; -{ - /* - * 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. - */ -int -procfs_access(v) - void *v; -{ - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vattr va; - int error; - - if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) - return (error); - - return (vaccess(va.va_type, va.va_mode, - va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); -} - -/* - * lookup. this is incredibly complicated in the - * general case, however for most pseudo-filesystems - * very little needs to be done. - * - * Locking isn't hard here, just poorly documented. - * - * If we're looking up ".", just vref the parent & return it. - * - * If we're looking up "..", unlock the parent, and lock "..". If everything - * went ok, and we're on the last component and the caller requested the - * parent locked, try to re-lock the parent. We do this to prevent lock - * races. - * - * For anything else, get the needed node. Then unlock the parent if not - * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the - * parent in the .. case). - * - * We try to exit with the parent locked in error cases. - */ -int -procfs_lookup(v) - void *v; -{ - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap = v; - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - const char *pname = cnp->cn_nameptr; - const struct proc_target *pt = NULL; - struct vnode *fvp; - pid_t pid; - struct pfsnode *pfs; - struct proc *p = NULL; - int i, error, wantpunlock, iscurproc = 0, isself = 0; - - *vpp = NULL; - cnp->cn_flags &= ~PDIRUNLOCK; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - return (0); - } - - wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN)); - pfs = VTOPFS(dvp); - switch (pfs->pfs_type) { - case PFSroot: - /* - * Shouldn't get here with .. in the root node. - */ - if (cnp->cn_flags & ISDOTDOT) - return (EIO); - - iscurproc = CNEQ(cnp, "curproc", 7); - isself = CNEQ(cnp, "self", 4); - - if (iscurproc || isself) { - error = procfs_allocvp(dvp->v_mount, vpp, 0, - iscurproc ? PFScurproc : PFSself, -1); - if ((error == 0) && (wantpunlock)) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - } - - for (i = 0; i < nproc_root_targets; i++) { - pt = &proc_root_targets[i]; - if (cnp->cn_namelen == pt->pt_namlen && - memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && - (pt->pt_valid == NULL || - (*pt->pt_valid)(p, dvp->v_mount))) - break; - } - - if (i != nproc_root_targets) { - error = procfs_allocvp(dvp->v_mount, vpp, 0, - pt->pt_pfstype, -1); - if ((error == 0) && (wantpunlock)) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - } - - pid = (pid_t)atoi(pname, cnp->cn_namelen); - - p = PFIND(pid); - if (p == NULL) - break; - - error = procfs_allocvp(dvp->v_mount, vpp, pid, PFSproc, -1); - if ((error == 0) && (wantpunlock)) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - - case PFSproc: - /* - * do the .. dance. We unlock the directory, and then - * get the root dir. That will automatically return .. - * locked. Then if the caller wanted dvp locked, we - * re-lock. - */ - if (cnp->cn_flags & ISDOTDOT) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - error = procfs_root(dvp->v_mount, vpp); - if ((error == 0) && (wantpunlock == 0) && - ((error = vn_lock(dvp, LK_EXCLUSIVE)) == 0)) - cnp->cn_flags &= ~PDIRUNLOCK; - return (error); - } - - 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 && - memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && - (pt->pt_valid == NULL || - (*pt->pt_valid)(p, dvp->v_mount))) - goto found; - } - break; - - found: - if (pt->pt_pfstype == PFSfile) { - fvp = p->p_textvp; - /* We already checked that it exists. */ - VREF(fvp); - vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); - if (wantpunlock) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - *vpp = fvp; - return (0); - } - - error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - pt->pt_pfstype, -1); - if ((error == 0) && (wantpunlock)) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return (error); - - case PFSfd: { - int fd; - struct file *fp; - /* - * do the .. dance. We unlock the directory, and then - * get the proc dir. That will automatically return .. - * locked. Then if the caller wanted dvp locked, we - * re-lock. - */ - if (cnp->cn_flags & ISDOTDOT) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFSproc, -1); - if ((error == 0) && (wantpunlock == 0) && - ((error = vn_lock(dvp, LK_EXCLUSIVE)) == 0)) - cnp->cn_flags &= ~PDIRUNLOCK; - return (error); - } - fd = atoi(pname, cnp->cn_namelen); - p = PFIND(pfs->pfs_pid); - if (p == NULL || (fp = fd_getfile(p->p_fd, fd)) == NULL) - return ENOENT; - FILE_USE(fp); - - switch (fp->f_type) { - case DTYPE_VNODE: - fvp = (struct vnode *)fp->f_data; - - /* Don't show directories */ - if (fvp->v_type == VDIR) - goto symlink; - - VREF(fvp); - FILE_UNUSE(fp, p); - vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY | - (p == curproc ? LK_CANRECURSE : 0)); - *vpp = fvp; - error = 0; - break; - default: - symlink: - FILE_UNUSE(fp, p); - error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFSfd, fd); - break; - } - if ((error == 0) && (wantpunlock)) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return error; - } - default: - return (ENOTDIR); - } - - return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); -} - -int -procfs_validfile(p, mp) - struct proc *p; - struct mount *mp; -{ - return (p->p_textvp != NULL); -} - -static int -procfs_validfile_linux(p, mp) - struct proc *p; - struct mount *mp; -{ - int flags; - - flags = VFSTOPROC(mp)->pmnt_flags; - return ((flags & PROCFSMNT_LINUXCOMPAT) && - (p == NULL || procfs_validfile(p, mp))); -} - -struct procfs_root_readdir_ctx { - struct uio *uiop; - off_t *cookies; - int ncookies; - off_t off; - off_t startoff; - int error; -}; - -static int -procfs_root_readdir_callback(struct proc *p, void *arg) -{ - struct procfs_root_readdir_ctx *ctxp = arg; - struct dirent d; - struct uio *uiop; - int error; - - uiop = ctxp->uiop; - if (uiop->uio_resid < UIO_MX) - return -1; /* no space */ - - if (ctxp->off < ctxp->startoff) { - ctxp->off++; - return 0; - } - - memset(&d, 0, UIO_MX); - d.d_reclen = UIO_MX; - d.d_fileno = PROCFS_FILENO(p->p_pid, PFSproc, -1); - d.d_namlen = snprintf(d.d_name, - UIO_MX - offsetof(struct dirent, d_name), "%ld", (long)p->p_pid); - d.d_type = DT_DIR; - - proclist_unlock_read(); - error = uiomove(&d, UIO_MX, uiop); - proclist_lock_read(); - if (error) { - ctxp->error = error; - return -1; - } - - ctxp->ncookies++; - if (ctxp->cookies) - *(ctxp->cookies)++ = ctxp->off + 1; - ctxp->off++; - - return 0; -} - -/* - * readdir returns directory entries from pfsnode (vp). - * - * the strategy here with procfs is to generate a single - * directory entry at a time (struct dirent) and then - * copy that out to userland using uiomove. a more efficent - * though more complex implementation, would try to minimize - * the number of calls to uiomove(). for procfs, this is - * hardly worth the added code complexity. - * - * this should just be done through read() - */ -int -procfs_readdir(v) - void *v; -{ - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - off_t **a_cookies; - int *a_ncookies; - } */ *ap = v; - struct uio *uio = ap->a_uio; - struct dirent d; - struct pfsnode *pfs; - off_t i; - int error; - off_t *cookies = NULL; - int ncookies; - struct vnode *vp; - const struct proc_target *pt; - struct procfs_root_readdir_ctx ctx; - - vp = ap->a_vp; - pfs = VTOPFS(vp); - - if (uio->uio_resid < UIO_MX) - return (EINVAL); - if (uio->uio_offset < 0) - return (EINVAL); - - error = 0; - i = uio->uio_offset; - memset(&d, 0, UIO_MX); - d.d_reclen = UIO_MX; - ncookies = uio->uio_resid / UIO_MX; - - 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 PFSproc: { - struct proc *p; - - if (i >= nproc_targets) - return 0; - - p = PFIND(pfs->pfs_pid); - if (p == NULL) - break; - - if (ap->a_ncookies) { - ncookies = min(ncookies, (nproc_targets - i)); - cookies = malloc(ncookies * sizeof (off_t), - M_TEMP, M_WAITOK); - *ap->a_cookies = cookies; - } - - for (pt = &proc_targets[i]; - uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { - if (pt->pt_valid && - (*pt->pt_valid)(p, vp->v_mount) == 0) - continue; - - d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, - pt->pt_pfstype, -1); - d.d_namlen = pt->pt_namlen; - memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); - d.d_type = pt->pt_type; - - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - } - - break; - } - case PFSfd: { - struct proc *p; - struct filedesc *fdp; - struct file *fp; - int lim, nc = 0; - - p = PFIND(pfs->pfs_pid); - if (p == NULL) - return ESRCH; - - fdp = p->p_fd; - - lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); - if (i >= lim) - return 0; - - if (ap->a_ncookies) { - ncookies = min(ncookies, (fdp->fd_nfiles + 2 - i)); - cookies = malloc(ncookies * sizeof (off_t), - M_TEMP, M_WAITOK); - *ap->a_cookies = cookies; - } - - for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { - pt = &proc_targets[i]; - d.d_namlen = pt->pt_namlen; - d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, - pt->pt_pfstype, -1); - (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); - d.d_type = pt->pt_type; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - nc++; - } - if (error) { - ncookies = nc; - break; - } - for (; uio->uio_resid >= UIO_MX && i < fdp->fd_nfiles; i++) { - /* check the descriptor exists */ - if ((fp = fd_getfile(fdp, i - 2)) == NULL) - continue; - simple_unlock(&fp->f_slock); - - d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2); - d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), - "%lld", (long long)(i - 2)); - d.d_type = VREG; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - nc++; - } - ncookies = nc; - break; - } - - /* - * this is for the root of the procfs filesystem - * what is needed are special entries for "curproc" - * and "self" followed by an entry for each process - * on allproc. - */ - - case PFSroot: { - int nc = 0; - - if (ap->a_ncookies) { - /* - * XXX Potentially allocating too much space here, - * but I'm lazy. This loop needs some work. - */ - cookies = malloc(ncookies * sizeof (off_t), - M_TEMP, M_WAITOK); - *ap->a_cookies = cookies; - } - error = 0; - /* 0 ... 3 are static entries. */ - for (; i <= 3 && uio->uio_resid >= UIO_MX; i++) { - switch (i) { - case 0: /* `.' */ - case 1: /* `..' */ - d.d_fileno = PROCFS_FILENO(0, PFSroot, -1); - d.d_namlen = i + 1; - memcpy(d.d_name, "..", d.d_namlen); - d.d_name[i + 1] = '\0'; - d.d_type = DT_DIR; - break; - - case 2: - d.d_fileno = PROCFS_FILENO(0, PFScurproc, -1); - d.d_namlen = sizeof("curproc") - 1; - memcpy(d.d_name, "curproc", sizeof("curproc")); - d.d_type = DT_LNK; - break; - - case 3: - d.d_fileno = PROCFS_FILENO(0, PFSself, -1); - d.d_namlen = sizeof("self") - 1; - memcpy(d.d_name, "self", sizeof("self")); - d.d_type = DT_LNK; - break; - } - - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - nc++; - if (cookies) - *cookies++ = i + 1; - } - /* 4 ... are process entries. */ - ctx.uiop = uio; - ctx.error = 0; - ctx.off = 4; - ctx.startoff = i; - ctx.cookies = cookies; - ctx.ncookies = nc; - proclist_foreach_call(&allproc, - procfs_root_readdir_callback, &ctx); - cookies = ctx.cookies; - nc = ctx.ncookies; - error = ctx.error; - if (error) - break; - - /* misc entries. */ - if (i < ctx.off) - i = ctx.off; - if (i >= ctx.off + nproc_root_targets) - break; - for (pt = &proc_root_targets[i - ctx.off]; - uio->uio_resid >= UIO_MX && - pt < &proc_root_targets[nproc_root_targets]; - pt++, i++) { - if (pt->pt_valid && - (*pt->pt_valid)(NULL, vp->v_mount) == 0) - continue; - d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1); - d.d_namlen = pt->pt_namlen; - memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); - d.d_type = pt->pt_type; - - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - nc++; - if (cookies) - *cookies++ = i + 1; - } - - ncookies = nc; - break; - } - - default: - error = ENOTDIR; - break; - } - - if (ap->a_ncookies) { - if (error) { - if (cookies) - free(*ap->a_cookies, M_TEMP); - *ap->a_ncookies = 0; - *ap->a_cookies = NULL; - } else - *ap->a_ncookies = ncookies; - } - uio->uio_offset = i; - return (error); -} - -/* - * readlink reads the link of `curproc' - */ -int -procfs_readlink(v) - void *v; -{ - struct vop_readlink_args *ap = v; - char buf[16]; /* should be enough */ - char *bp = buf; - char *path = NULL; - int len; - int error = 0; - struct pfsnode *pfs = VTOPFS(ap->a_vp); - - if (pfs->pfs_fileno == PROCFS_FILENO(0, PFScurproc, -1)) - len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - else if (pfs->pfs_fileno == PROCFS_FILENO(0, PFSself, -1)) - len = snprintf(buf, sizeof(buf), "%s", "curproc"); - else { - struct file *fp; - struct proc *pown; - struct vnode *vxp, *vp; - - if ((error = procfs_getfp(pfs, &pown, &fp)) != 0) - return error; - FILE_USE(fp); - switch (fp->f_type) { - case DTYPE_VNODE: - vxp = (struct vnode *)fp->f_data; - if (vxp->v_type != VDIR) { - FILE_UNUSE(fp, pown); - return EINVAL; - } - if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK)) - == NULL) { - FILE_UNUSE(fp, pown); - return ENOMEM; - } - bp = path + MAXPATHLEN; - *--bp = '\0'; - vp = curproc->p_cwdi->cwdi_rdir; - if (vp == NULL) - vp = rootvnode; - error = getcwd_common(vxp, vp, &bp, path, - MAXPATHLEN / 2, 0, curproc); - FILE_UNUSE(fp, pown); - if (error) { - free(path, M_TEMP); - return error; - } - len = strlen(bp); - break; - - case DTYPE_MISC: - len = snprintf(buf, sizeof(buf), "%s", "[misc]"); - break; - - case DTYPE_KQUEUE: - len = snprintf(buf, sizeof(buf), "%s", "[kqueue]"); - break; - - default: - return EINVAL; - } - } - - error = uiomove(bp, len, ap->a_uio); - if (path) - free(path, M_TEMP); - return error; -} - -/* - * convert decimal ascii to int - */ -static int -atoi(b, len) - const char *b; - size_t len; -{ - int p = 0; - - while (len--) { - char c = *b++; - if (c < '0' || c > '9') - return -1; - p = 10 * p + (c - '0'); - } - - return p; -} diff -r -u -N --exclude CVS NetBSD-3.1/sys/net/bpf.c mult-netbsd-3.1/sys/net/bpf.c --- NetBSD-3.1/sys/net/bpf.c 2005-02-26 22:45:09.000000000 +0000 +++ mult-netbsd-3.1/sys/net/bpf.c 2007-12-18 10:59:49.000000000 +0000 @@ -540,8 +540,11 @@ struct bpf_d *d; { wakeup(d); - if (d->bd_async) - fownsignal(d->bd_pgid, SIGIO, 0, 0, NULL); + if (d->bd_async){ + /* FIXME - instance */ + printf("%s: defaulting to proc0 instance\n", __func__); + fownsignal(proc0.p_inst, d->bd_pgid, SIGIO, 0, 0, NULL); + } selnotify(&d->bd_sel, 0); /* XXX */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/net/if_tap.c mult-netbsd-3.1/sys/net/if_tap.c --- NetBSD-3.1/sys/net/if_tap.c 2006-01-21 05:40:24.000000000 +0000 +++ mult-netbsd-3.1/sys/net/if_tap.c 2007-12-18 10:59:49.000000000 +0000 @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -462,9 +463,12 @@ ifp->if_flags |= IFF_OACTIVE; wakeup(sc); selnotify(&sc->sc_rsel, 1); - if (sc->sc_flags & TAP_ASYNCIO) - fownsignal(sc->sc_pgid, SIGIO, POLL_IN, + if (sc->sc_flags & TAP_ASYNCIO) { + /* FIXME - instance */ + printf("%s: defaulting to proc0 instance\n", __func__); + fownsignal(proc0.p_inst, sc->sc_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM, NULL); + } } } @@ -554,8 +558,11 @@ ifp->if_flags &= ~IFF_RUNNING; wakeup(sc); selnotify(&sc->sc_rsel, 1); - if (sc->sc_flags & TAP_ASYNCIO) - fownsignal(sc->sc_pgid, SIGIO, POLL_HUP, 0, NULL); + if (sc->sc_flags & TAP_ASYNCIO) { + /* FIXME - instance */ + printf("%s: defaulting to proc0 instance\n", __func__); + fownsignal(proc0.p_inst, sc->sc_pgid, SIGIO, POLL_HUP, 0, NULL); + } } /* diff -r -u -N --exclude CVS NetBSD-3.1/sys/net/if_tun.c mult-netbsd-3.1/sys/net/if_tun.c --- NetBSD-3.1/sys/net/if_tun.c 2005-01-24 21:25:09.000000000 +0000 +++ mult-netbsd-3.1/sys/net/if_tun.c 2007-12-18 10:59:49.000000000 +0000 @@ -64,6 +64,7 @@ #endif #include +#include #define TUNDEBUG if (tundebug) printf int tundebug = 0; @@ -254,8 +255,11 @@ tp->tun_flags &= ~TUN_RWAIT; wakeup((caddr_t)tp); } - if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) - fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL); + if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) { + /* FIXME - instance */ + printf("%s: defaulting to proc0 instance\n", __func__); + fownsignal(proc0.p_inst, tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL); + } selwakeup(&tp->tun_rsel); @@ -557,9 +561,12 @@ tp->tun_flags &= ~TUN_RWAIT; wakeup((caddr_t)tp); } - if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) - fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM, + if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) { + /* FIXME - instance */ + printf("%s: defaulting to proc0 instance\n", __func__); + fownsignal(proc0.p_inst, tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM, NULL); + } selnotify(&tp->tun_rsel, 0); out: diff -r -u -N --exclude CVS NetBSD-3.1/sys/net80211/ieee80211_ioctl.c mult-netbsd-3.1/sys/net80211/ieee80211_ioctl.c --- NetBSD-3.1/sys/net80211/ieee80211_ioctl.c 2005-02-26 22:45:09.000000000 +0000 +++ mult-netbsd-3.1/sys/net80211/ieee80211_ioctl.c 2007-11-09 18:23:30.000000000 +0000 @@ -113,11 +113,15 @@ /* nothing appropriate */ break; case WI_RID_NODENAME: +#if 0 + /* FIXME: needs to be instance-switched. */ strlcpy((char *)&wreq.wi_val[1], hostname, sizeof(wreq.wi_val) - sizeof(wreq.wi_val[0])); wreq.wi_val[0] = htole16(strlen(hostname)); wreq.wi_len = (1 + strlen(hostname) + 1) / 2; break; +#endif + return(EINVAL); case WI_RID_CURRENT_SSID: if (ic->ic_state != IEEE80211_S_RUN) { wreq.wi_val[0] = 0; diff -r -u -N --exclude CVS NetBSD-3.1/sys/netinet6/icmp6.c mult-netbsd-3.1/sys/netinet6/icmp6.c --- NetBSD-3.1/sys/netinet6/icmp6.c 2005-01-17 10:16:07.000000000 +0000 +++ mult-netbsd-3.1/sys/netinet6/icmp6.c 2007-11-09 18:23:30.000000000 +0000 @@ -150,13 +150,13 @@ static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int)); static const char *icmp6_redirect_diag __P((struct in6_addr *, struct in6_addr *, struct in6_addr *)); -static struct mbuf *ni6_input __P((struct mbuf *, int)); -static struct mbuf *ni6_nametodns __P((const char *, int, int)); -static int ni6_dnsmatch __P((const char *, int, const char *, int)); -static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *, - struct ifnet **, char *)); -static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, - struct ifnet *, int)); +/*static struct mbuf *ni6_input __P((struct mbuf *, int));*/ +/*static struct mbuf *ni6_nametodns __P((const char *, int, int));*/ +/*static int ni6_dnsmatch __P((const char *, int, const char *, int));*/ +/*static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *, + struct ifnet **, char *));*/ +/*static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, + struct ifnet *, int));*/ static int icmp6_notify_error __P((struct mbuf *, int, int, int)); static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *)); static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *)); @@ -675,6 +675,8 @@ break; /* just pass it to applications */ case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ +#if 0 + /* FIXME: needs to be instance-switched. */ { enum { WRU, FQDN } mode; @@ -750,6 +752,8 @@ } break; } +#endif + return(-1); case ICMP6_WRUREPLY: if (code != 0) @@ -1173,6 +1177,7 @@ #ifndef offsetof /* XXX */ #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif +#if 0 static struct mbuf * ni6_input(m, off) struct mbuf *m; @@ -1183,7 +1188,7 @@ u_int16_t qtype; int subjlen; int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo); - struct ni_reply_fqdn *fqdn; + /*struct ni_reply_fqdn *fqdn;*/ int addrs; /* for NI_QTYPE_NODEADDR */ struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */ struct sockaddr_in6 sin6; /* double meaning; ip6_dst and subjectaddr */ @@ -1303,6 +1308,8 @@ * wildcard match, if gethostname(3) side has * truncated hostname. */ +#if 0 + /* FIXME - this needs to be instance-switched. */ n = ni6_nametodns(hostname, hostnamelen, 0); if (!n || n->m_next || n->m_len == 0) goto bad; @@ -1317,6 +1324,8 @@ m_freem(n); n = NULL; break; +#endif + return(NULL); case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */ default: @@ -1415,6 +1424,8 @@ break; } case NI_QTYPE_FQDN: +#if 0 + /* FIXME: needs to be instance-switched. */ nni6->ni_code = ICMP6_NI_SUCCESS; fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) + sizeof(struct ip6_hdr) + @@ -1432,6 +1443,8 @@ goto bad; n->m_pkthdr.len += n->m_next->m_len; break; +#endif + return(NULL); case NI_QTYPE_NODEADDR: { int lenlim, copied; @@ -1460,6 +1473,7 @@ m_freem(n); return (NULL); } +#endif #undef hostnamelen #define isupper(x) ('A' <= (x) && (x) <= 'Z') @@ -1473,6 +1487,7 @@ * XXX names with less than 2 dots (like "foo" or "foo.section") will be * treated as truncated name (two \0 at the end). this is a wild guess. */ +#if 0 static struct mbuf * ni6_nametodns(name, namelen, old) const char *name; @@ -1577,12 +1592,14 @@ m_freem(m); return NULL; } +#endif /* * check if two DNS-encoded string matches. takes care of truncated * form (with \0\0 at the end). no compression support. * XXX upper/lowercase match (see RFC2065) */ +#if 0 static int ni6_dnsmatch(a, alen, b, blen) const char *a; @@ -1643,10 +1660,12 @@ else return 0; } +#endif /* * calculate the number of addresses to be returned in the node info reply. */ +#if 0 static int ni6_addrs(ni6, m, ifpp, subj) struct icmp6_nodeinfo *ni6; @@ -1740,7 +1759,9 @@ return (addrs); } +#endif +#if 0 static int ni6_store_addrs(ni6, nni6, ifp0, resid) struct icmp6_nodeinfo *ni6, *nni6; @@ -1883,6 +1904,7 @@ return (copied); } +#endif /* * XXX almost dup'ed code with rip6_input. diff -r -u -N --exclude CVS NetBSD-3.1/sys/netinet6/in6.c mult-netbsd-3.1/sys/netinet6/in6.c --- NetBSD-3.1/sys/netinet6/in6.c 2005-02-01 15:29:23.000000000 +0000 +++ mult-netbsd-3.1/sys/netinet6/in6.c 2007-11-09 18:23:30.000000000 +0000 @@ -1153,6 +1153,8 @@ /* * join node information group address */ +#if 0 + /* FIXME - needs to be instance-switched. */ if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) == 0) { imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); if (!imm) { @@ -1166,6 +1168,7 @@ imm, i6mm_chain); } } +#endif if (ifp->if_flags & IFF_LOOPBACK) { /* diff -r -u -N --exclude CVS NetBSD-3.1/sys/netinet6/in6_ifattach.c mult-netbsd-3.1/sys/netinet6/in6_ifattach.c --- NetBSD-3.1/sys/netinet6/in6_ifattach.c 2004-04-20 18:12:03.000000000 +0100 +++ mult-netbsd-3.1/sys/netinet6/in6_ifattach.c 2007-11-09 18:23:30.000000000 +0000 @@ -91,14 +91,14 @@ struct ifnet *ifp; struct in6_addr *in6; /* upper 64bits are preserved */ { +#if 0 + /* FIXME - this needs instance-separation */ MD5_CTX ctxt; u_int8_t digest[16]; -#if 0 /* we need at least several letters as seed for ifid */ if (hostnamelen < 3) return -1; -#endif /* generate 8 bytes of pseudo-random value. */ bzero(&ctxt, sizeof(ctxt)); @@ -108,6 +108,8 @@ /* assumes sizeof(digest) > sizeof(ifid) */ bcopy(digest, &in6->s6_addr[8], 8); +#endif + bzero(&in6->s6_addr[8], 8); /* make sure to set "u" bit to local, and "g" bit to individual. */ in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/nfs/nfs_bootdhcp.c mult-netbsd-3.1/sys/nfs/nfs_bootdhcp.c --- NetBSD-3.1/sys/nfs/nfs_bootdhcp.c 2005-02-26 22:39:50.000000000 +0000 +++ mult-netbsd-3.1/sys/nfs/nfs_bootdhcp.c 2007-11-09 19:05:28.000000000 +0000 @@ -718,18 +718,18 @@ memcpy(&gateway, p, 4); break; case TAG_HOST_NAME: - if (len >= sizeof(hostname)) { + if (len >= MAXHOSTNAMELEN) { printf("nfs_boot: host name >= %lu bytes", - (u_long)sizeof(hostname)); + (u_long)MAXHOSTNAMELEN); break; } myname = p; mynamelen = len; break; case TAG_DOMAIN_NAME: - if (len >= sizeof(domainname)) { + if (len >= MAXHOSTNAMELEN) { printf("nfs_boot: domain name >= %lu bytes", - (u_long)sizeof(domainname)); + (u_long)MAXHOSTNAMELEN); break; } mydomain = p; @@ -769,6 +769,8 @@ /* * Store and print network config info. */ +#if 0 + /* FIXME - needs instance-switching */ if (myname) { myname[mynamelen] = '\0'; strncpy(hostname, myname, sizeof(hostname)); @@ -781,6 +783,7 @@ domainnamelen = mydomainlen; printf("nfs_boot: my_domain=%s\n", domainname); } +#endif nd->nd_myip = bootp->bp_yiaddr; if (nd->nd_myip.s_addr) printf("nfs_boot: my_addr=%s\n", inet_ntoa(nd->nd_myip)); diff -r -u -N --exclude CVS NetBSD-3.1/sys/nfs/nfs_bootparam.c mult-netbsd-3.1/sys/nfs/nfs_bootparam.c --- NetBSD-3.1/sys/nfs/nfs_bootparam.c 2004-05-22 23:52:15.000000000 +0100 +++ mult-netbsd-3.1/sys/nfs/nfs_bootparam.c 2007-11-14 16:00:24.000000000 +0000 @@ -56,6 +56,8 @@ #include #include #include +#include +#include #include #include @@ -115,15 +117,15 @@ struct proc *procp; { struct ifnet *ifp = nd->nd_ifp; - struct in_addr my_ip, arps_ip, gw_ip; + struct in_addr my_ip, arps_ip, gw_ip; struct sockaddr_in bp_sin; struct sockaddr_in *sin; #ifndef NFS_BOOTPARAM_NOGATEWAY struct nfs_dlmount *gw_ndm = 0; - char *p; - u_int32_t mask; + char *p; + u_int32_t mask; #endif - int error; + int error; /* * Bring up the interface. (just set the "up" flag) @@ -186,7 +188,7 @@ goto delout; } printf("nfs_boot: server_addr=%s\n", inet_ntoa(sin->sin_addr)); - printf("nfs_boot: hostname=%s\n", hostname); + /*printf("nfs_boot: hostname=%s\n", hostbuf);*/ /* * Now fetch the server:pathname strings and server IP @@ -310,10 +312,13 @@ /* encapsulated data here */ } *reply; - struct mbuf *m, *from; + struct mbuf *m, *from; struct sockaddr_in *sin; - int error; - int16_t port; + int error; + int16_t port; + char hostbuf[MAXHOSTNAMELEN], + dombuf[MAXHOSTNAMELEN]; + size_t hostbuflen, dombuflen; /* * Build request message for PMAPPROC_CALLIT. @@ -359,14 +364,20 @@ bpsin->sin_addr.s_addr = sin->sin_addr.s_addr; /* client name */ - hostnamelen = MAXHOSTNAMELEN-1; - m = xdr_string_decode(m, hostname, &hostnamelen); + + hostbuflen = inst_get_phostnamelen(p); + inst_get_phostname(p, hostbuf, MAXHOSTNAMELEN); + + m = xdr_string_decode(m, hostbuf, &hostbuflen); if (m == NULL) goto bad; /* domain name */ - domainnamelen = MAXHOSTNAMELEN-1; - m = xdr_string_decode(m, domainname, &domainnamelen); + + dombuflen = inst_get_pdomainnamelen(p); + inst_get_pdomainname(p, dombuf, MAXHOSTNAMELEN); + + m = xdr_string_decode(m, dombuf, &dombuflen); if (m == NULL) goto bad; @@ -405,19 +416,24 @@ struct nfs_dlmount *ndm; struct proc *p; { - char pathname[MNAMELEN]; - struct in_addr inaddr; + char pathname[MNAMELEN]; + struct in_addr inaddr; struct sockaddr_in *sin; - struct mbuf *m; - char *serv_name; - int error, sn_len, path_len; + struct mbuf *m; + char *serv_name; + int error, sn_len, path_len; + char hostbuf[MAXHOSTNAMELEN]; + size_t hostbuflen; /* * Build request message. */ /* client name (hostname) */ - m = xdr_string_encode(hostname, hostnamelen); + hostbuflen = inst_get_phostnamelen(p); + inst_get_phostname(p, hostbuf, MAXHOSTNAMELEN); + + m = xdr_string_encode(hostbuf, hostbuflen); if (m == NULL) return (ENOMEM); diff -r -u -N --exclude CVS NetBSD-3.1/sys/nfs/nfs_node.c mult-netbsd-3.1/sys/nfs/nfs_node.c --- NetBSD-3.1/sys/nfs/nfs_node.c 2005-08-24 19:43:37.000000000 +0100 +++ mult-netbsd-3.1/sys/nfs/nfs_node.c 2007-11-18 14:10:51.000000000 +0000 @@ -207,6 +207,7 @@ * overwrite these. */ np->n_rcred = curproc->p_ucred; + /* FIXME - instances */ crhold(np->n_rcred); np->n_wcred = curproc->p_ucred; crhold(np->n_wcred); diff -r -u -N --exclude CVS NetBSD-3.1/sys/nfs/nfs_vfsops.c mult-netbsd-3.1/sys/nfs/nfs_vfsops.c --- NetBSD-3.1/sys/nfs/nfs_vfsops.c 2005-09-27 11:31:29.000000000 +0100 +++ mult-netbsd-3.1/sys/nfs/nfs_vfsops.c 2007-11-09 18:23:31.000000000 +0000 @@ -155,8 +155,7 @@ #endif vp = nmp->nm_vnode; np = VTONFS(vp); - cred = crget(); - cred->cr_ngroups = 0; + cred = crdupinst(p->p_ucred); #ifndef NFS_V2_ONLY if (v3 && (nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, p); @@ -778,10 +777,9 @@ MALLOC(attrs, struct vattr *, sizeof(struct vattr), M_TEMP, M_WAITOK); VOP_GETATTR(*vpp, attrs, p->p_ucred, p); if ((nmp->nm_flag & NFSMNT_NFSV3) && ((*vpp)->v_type == VDIR)) { - cr = crget(); + cr = crdupinst(p->p_ucred); cr->cr_uid = attrs->va_uid; cr->cr_gid = attrs->va_gid; - cr->cr_ngroups = 0; nfs_cookieheuristic(*vpp, &nmp->nm_iflag, p, cr); crfree(cr); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/nfs/nfs_vnops.c mult-netbsd-3.1/sys/nfs/nfs_vnops.c --- NetBSD-3.1/sys/nfs/nfs_vnops.c 2006-07-16 13:21:21.000000000 +0100 +++ mult-netbsd-3.1/sys/nfs/nfs_vnops.c 2007-11-18 14:10:51.000000000 +0000 @@ -475,12 +475,14 @@ if (np->n_rcred != NULL) crfree(np->n_rcred); np->n_rcred = ap->a_cred; + /* FIXME - instances */ crhold(np->n_rcred); } if (ap->a_mode & FWRITE) { if (np->n_wcred != NULL) crfree(np->n_wcred); np->n_wcred = ap->a_cred; + /* FIXME - instances */ crhold(np->n_wcred); } diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/Makefile mult-netbsd-3.1/sys/sys/Makefile --- NetBSD-3.1/sys/sys/Makefile 2005-01-02 16:08:30.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/Makefile 2007-11-15 13:34:52.000000000 +0000 @@ -13,6 +13,7 @@ fcntl.h fdio.h featuretest.h file.h filedesc.h filio.h \ float_ieee754.h fstypes.h gmon.h hash.h \ ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h ipc.h \ + inst.h \ joystick.h \ kcore.h kgdb.h ksem.h ksyms.h ktrace.h \ lkm.h localedef.h lock.h lockf.h lwp.h \ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/event.h mult-netbsd-3.1/sys/sys/event.h --- NetBSD-3.1/sys/sys/event.h 2005-02-26 22:25:34.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/event.h 2007-11-26 15:08:35.000000000 +0000 @@ -199,14 +199,15 @@ }; struct proc; +struct inst; void knote(struct klist *, long); void knote_remove(struct proc *, struct klist *); void knote_fdclose(struct proc *, int); int kqueue_register(struct kqueue *, struct kevent *, struct proc *); -int kfilter_register(const char *, const struct filterops *, int *); -int kfilter_unregister(const char *); +int kfilter_register(struct inst *, const char *, const struct filterops *, int *); +int kfilter_unregister(struct inst *, const char *); int filt_seltrue(struct knote *, long); int seltrue_kqfilter(dev_t, struct knote *); diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/file.h mult-netbsd-3.1/sys/sys/file.h --- NetBSD-3.1/sys/sys/file.h 2005-02-12 23:14:03.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/file.h 2007-11-14 16:00:24.000000000 +0000 @@ -149,9 +149,7 @@ #define FOF_UPDATE_OFFSET 0x01 /* update the file offset */ LIST_HEAD(filelist, file); -extern struct filelist filehead; /* head of list of open files */ extern int maxfiles; /* kernel limit on # of open files */ -extern int nfiles; /* actual number of open files */ extern const struct fileops vnops; /* vnode operations for files */ @@ -167,7 +165,15 @@ int fsetown(struct proc *, pid_t *, int, const void *); int fgetown(struct proc *, pid_t, int, void *); -void fownsignal(pid_t, int, int, int, void *); + +/* + * Send signal to descriptor owner, either process or process group, + * within the instance context i. + */ +void +fownsignal(struct inst *i, pid_t pgid, int signo, + int code, int band, void *fdescdata); + int fdclone(struct proc *, struct file *, int, int, const struct fileops *, void *); diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/filedesc.h mult-netbsd-3.1/sys/sys/filedesc.h --- NetBSD-3.1/sys/sys/filedesc.h 2004-06-10 07:15:23.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/filedesc.h 2007-11-18 14:10:51.000000000 +0000 @@ -135,7 +135,7 @@ int falloc(struct proc *, struct file **, int *); void ffree(struct file *); struct filedesc *fdcopy(struct proc *); -struct filedesc *fdinit(struct proc *); +struct filedesc *fdinit(void); void fdshare(struct proc *, struct proc *); void fdunshare(struct proc *); void fdinit1(struct filedesc0 *); diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/inst.h mult-netbsd-3.1/sys/sys/inst.h --- NetBSD-3.1/sys/sys/inst.h 1970-01-01 01:00:00.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/inst.h 2007-12-19 13:35:20.000000000 +0000 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2007 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _SYS_INST_H +#define _SYS_INST_H + +/* + * The user-land component of this is very much under development. The + * following few structures are used in the instctl() system call in + * order to control underlying instances. + */ + +/* + * The following define instance states (i_state). + */ + +#define INST_INIT (0) /* Doesn't have init(8). */ +#define INST_RUNNING (1) /* Running (has init(8)). */ +#define INST_EXITING (2) /* Exited & waiting on init(8). */ +#define INST_REAPED (3) /* Exited & waiting for reap. */ + + +struct instctl_create +{ + const char *root; /* The chroot() (XXX - temporary). */ +}; + +struct instctl_kill +{ + unsigned int uuid; /* The target instance's uuid. */ + int sig; /* Which signal to send. */ +#define IC_KILLSLOW 0x00 /* SIGTERM to instinit(8) */ +#define IC_KILLFAST 0x01 /* SIGKILL to instinit(8) */ +}; + +struct instctl +{ + int ic_op; /* Operation to perform. */ +#define IC_CREATE 0x00 /* Create an instance. */ +#define IC_DEBUG 0x01 /* Configure debugging. */ +#define IC_KILL 0x02 /* Kill an instance. */ + union { + struct instctl_create ic_create; + int ic_debug; +#define IC_NONE 0x00 /* No debugging messages. */ +#define IC_ALLOC 0x01 /* Instance alloc/free. */ +#define IC_REFCNT 0x02 /* Change to refcount. */ +#define IC_SYSCALL 0x04 /* Report inst syscalls. */ +#define IC_DAEMON 0x05 /* instdaemon(9) reports. */ +#define IC_ALL 0xffff /* All debugging messages. */ + struct instctl_kill ic_kill; + } ic_data; +}; + +#include + +__BEGIN_DECLS + +int instctl(const struct instctl *); + +__END_DECLS + +#ifdef _KERNEL + +MALLOC_DECLARE(M_INST); + +typedef struct inst_acct *inst_acct_t; +typedef struct inst_res *inst_res_t; +typedef struct inst_proc *inst_proc_t; +typedef struct inst_pipe *inst_pipe_t; +typedef struct inst_kevt *inst_kevt_t; +typedef struct inst_fork *inst_fork_t; +typedef struct inst_ktrc *inst_ktrc_t; + +#include +#include +#include +#include + +LIST_HEAD(instlist, inst); + +/* Maximum number of instances (XXX - hack). */ +#define INST_MAX (256) + +/* Kernel structure describing an instance context. This must contain + * all values required for instance processing. Locking is done on a + * per-structure level using the i_lock value. All modifications must + * be appropriately locked. */ +struct inst +{ + uint i_uuid; /* Global, unique id. */ + uint i_refcnt; /* Reference counter. */ + struct inst *i_parent; /* Parent inst (or NULL). */ + struct simplelock i_lock; /* Lock for all subs. */ + char i_host[MAXHOSTNAMELEN]; /* Hostname. */ + char i_domain[MAXHOSTNAMELEN]; /* Domainname. */ + LIST_ENTRY(inst) i_list; /* List of all instances. */ + + char i_root[MAXPATHLEN]; /* XXX - hack */ + + int i_state; /* State of the instance. */ + + inst_acct_t i_acct; + inst_res_t i_res; + inst_proc_t i_proc; + inst_pipe_t i_pipe; + inst_kevt_t i_kevt; + inst_fork_t i_fork; + inst_ktrc_t i_ktrc; + + /* + * These are counters for all entities contained by this + * instance. The instance should be locked in order to modify + * these values (i_nprocs needs the proclist lock, too). + */ + + int i_npipes; /* Number of allocated pipes. */ + int i_ncreds; /* Number of allocated creds. */ + int i_nprocs; /* Number of allocated procs. */ + int i_nsess; /* Number of allocated sesss. */ + int i_nfiles; /* Number of allocated files. */ + int i_nsocks; /* Number of allocated sockets. */ + + /* + * Processes contained within the instance. When modifying ANY + * of these, the process lock must be acquired. + */ + + struct lock i_proclist_lock;/* Lock for process lists. */ + struct lwplist i_alllwp; /* List of all lwps. */ + struct proclist i_allproc; /* List of all procs. */ + struct proclist i_zombproc; /* List of zombie procs. */ + struct proclist_desc i_proclists[3]; + struct proc *i_initproc; /* Link to init(8) process. */ + + /* + * Files contained within the instance. When modifying ANY of + * these, the file lock must be acquired. + */ + + struct filelist i_filehead; /* List of allocated files. */ + struct simplelock i_filelist_lock; /* Lock for file list. */ +}; + + +void instdaemon(void *); +__volatile int instdaemon_sem; + +/* + * Access of the global instance context. + */ +struct instlist allinst; + +/* + * NOTE that calling this function will put a hold on the instance so + * that it doesn't exit between executing this function and getting the + * result. This obviously isn't the case if the instance couldn't be + * found and NULL is returned. + */ +struct inst *inst_lookup(u_int uuid); + +/* + * Locking of the various parts and sub-parts. + */ +void instlist_lock_read(void); +void instlist_unlock_read(void); +void proclist_lock_read(struct inst *i); +void proclist_unlock_read(struct inst *); +int proclist_lock_write(struct inst *); +void proclist_unlock_write(struct inst *, int); + +/* + * Allocation and release of the actual instance structure. + */ +void inst_init(void); +#define INST_WAIT (0) +#define INST_NOWAIT (1) +struct inst *inst_alloc(int flags); + +/* + * Allocation and release of sub-structures. These follow the semantics + * for malloc() and free() (in terms of flags). + */ +int inst_res_alloc(inst_res_t *, int); +int inst_acct_alloc(inst_acct_t *, int); +int inst_proc_alloc(inst_proc_t *, int); +int inst_pipe_alloc(inst_pipe_t *, int); +int inst_kevt_alloc(inst_kevt_t *, int); +int inst_fork_alloc(inst_fork_t *, int); +int inst_ktrc_alloc(inst_ktrc_t *, int); + +void inst_proc_free(inst_proc_t); +void inst_res_free(inst_res_t); +void inst_acct_free(inst_acct_t); +void inst_pipe_free(inst_pipe_t); +void inst_kevt_free(inst_kevt_t); +void inst_fork_free(inst_fork_t); +void inst_ktrc_free(inst_ktrc_t); + +/* + * Reference acquisition and release. + */ +void inst_hold(struct inst *i); +void inst_release(struct inst *i); + +/* + * Possibly-deprecate these helper functions... + */ +void inst_get_hostname(struct lwp *l, + char *buf, size_t len); +void inst_get_phostname(struct proc *p, + char *buf, size_t len); +int inst_set_hostname(struct lwp *l, const char *buf); +size_t inst_get_hostnamelen(struct lwp *l); +size_t inst_get_phostnamelen(struct proc *p); +int inst_copyoutstr_hostname(struct lwp *l, + void *uaddr, size_t len, size_t *done); +int inst_copyout_hostname(struct lwp *l, void *uaddr, + size_t len); +void inst_get_domainname(struct lwp *l, char *buf, + size_t len); +void inst_get_pdomainname(struct proc *l, char *buf, + size_t len); +int inst_set_domainname(struct lwp *l, const char *buf); +size_t inst_get_domainnamelen(struct lwp *l); +size_t inst_get_pdomainnamelen(struct proc *p); + +#endif /* _KERNEL */ +#endif /* !_SYS_INST_H */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/kernel.h mult-netbsd-3.1/sys/sys/kernel.h --- NetBSD-3.1/sys/sys/kernel.h 2003-10-02 13:14:00.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/kernel.h 2007-11-09 19:05:28.000000000 +0000 @@ -43,10 +43,6 @@ /* Global variables for the kernel. */ extern long hostid; -extern char hostname[MAXHOSTNAMELEN]; -extern int hostnamelen; -extern char domainname[MAXHOSTNAMELEN]; -extern int domainnamelen; extern volatile struct timeval mono_time; extern struct timeval boottime; diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/lwp.h mult-netbsd-3.1/sys/sys/lwp.h --- NetBSD-3.1/sys/sys/lwp.h 2006-04-07 13:27:23.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/lwp.h 2007-11-18 14:10:51.000000000 +0000 @@ -47,6 +47,10 @@ #include #include + +LIST_HEAD(lwplist, lwp); + + struct lwp { struct lwp *l_forw; /* Doubly-linked run/sleep queue. */ struct lwp *l_back; @@ -54,6 +58,8 @@ struct proc *l_proc; /* Process with which we are associated. */ +#define l_inst l_proc->p_inst + LIST_ENTRY(lwp) l_sibling; /* Entry on process's list of LWPs. */ struct cpu_info * __volatile l_cpu; /* CPU we're running on if @@ -92,12 +98,12 @@ struct mdlwp l_md; /* Any machine-dependent fields. */ }; -LIST_HEAD(lwplist, lwp); /* a list of LWPs */ - -extern struct lwplist alllwp; /* List of all LWPs. */ +/* + * See lwp_pool. + */ +extern struct pool +lwp_uc_pool; -extern struct pool lwp_pool; /* memory pool for LWPs */ -extern struct pool lwp_uc_pool; /* memory pool for LWP startup args */ extern struct lwp lwp0; /* LWP for proc0 */ @@ -165,6 +171,7 @@ void cpu_switchto (struct lwp *, struct lwp *); #endif + int newlwp(struct lwp *, struct proc *, vaddr_t, int /* XXX boolean_t */, int, void *, size_t, void (*)(void *), void *, struct lwp **); @@ -176,7 +183,15 @@ void startlwp(void *); void upcallret(struct lwp *); void lwp_exit (struct lwp *); -void lwp_exit2 (struct lwp *); + +/* + * Release the memory resources of an LWP and put it back into the LWP + * pool. + */ +void +lwp_exit2(struct lwp *lwp); + + struct lwp *proc_representative_lwp(struct proc *); inline int lwp_suspend(struct lwp *, struct lwp *); #endif /* _KERNEL */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/pipe.h mult-netbsd-3.1/sys/sys/pipe.h --- NetBSD-3.1/sys/sys/pipe.h 2005-02-03 19:20:01.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/pipe.h 2007-11-14 17:12:02.000000000 +0000 @@ -100,6 +100,7 @@ * Two of these are linked together to produce bi-directional pipes. */ struct pipe { + struct inst *pipe_inst; /* pipe owning instance */ struct simplelock pipe_slock; /* pipe mutex */ struct lock pipe_lock; /* long-term pipe lock */ struct pipebuf pipe_buffer; /* data storage */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/proc.h mult-netbsd-3.1/sys/sys/proc.h --- NetBSD-3.1/sys/sys/proc.h 2006-04-07 13:31:52.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/proc.h 2007-12-16 14:56:45.000000000 +0000 @@ -53,20 +53,24 @@ #include #include + /* - * One structure allocated per session. + * One structure allocated per session. Each session is associated with + * an instance. */ struct session { int s_count; /* Ref cnt; pgrps in session */ u_int s_flags; #define S_LOGIN_SET 1 /* s_login set in this session */ struct proc *s_leader; /* Session leader */ + struct inst *s_inst; /* Instance of session */ struct vnode *s_ttyvp; /* Vnode of controlling terminal */ struct tty *s_ttyp; /* Controlling terminal */ char s_login[MAXLOGNAME]; /* Setlogin() name */ pid_t s_sid; /* Session ID (pid of leader) */ }; + /* * One structure allocated per process group. */ @@ -155,6 +159,7 @@ /* Substructures: */ struct pcred *p_cred; /* Process owner's identity */ + struct filedesc *p_fd; /* Ptr to open files structure */ struct cwdinfo *p_cwdi; /* cdir/rdir/cmask info */ struct pstats *p_stats; /* Accounting/statistics (PROC ONLY) */ @@ -165,6 +170,8 @@ void *p_ksems; /* p1003.1b semaphores */ #define p_ucred p_cred->pc_ucred +#define p_inst p_ucred->cr_inst + #define p_rlimit p_limit->pl_rlimit int p_exitsig; /* signal to sent to parent on exit */ @@ -211,7 +218,6 @@ int p_traceflag; /* Kernel trace points */ void *p_tracep; /* Trace private data */ - void *p_systrace; /* Back pointer to systrace */ struct vnode *p_textvp; /* Vnode of executable */ @@ -297,7 +303,6 @@ #define P_NOCLDWAIT 0x00020000 /* No zombies if child dies */ #define P_32 0x00040000 /* 32-bit process (used on 64-bit kernels) */ #define P_INEXEC 0x00100000 /* Process is exec'ing and can't be traced */ -#define P_SYSTRACE 0x00200000 /* Process system call tracing active */ #define P_CHTRACED 0x00400000 /* Child has been traced & reparented */ #define P_STOPFORK 0x00800000 /* Child will be stopped on fork(2) */ #define P_STOPEXEC 0x01000000 /* Will be stopped on exec(2) */ @@ -332,6 +337,17 @@ int p_refcnt; /* Number of references */ }; + +/* + * Put a pcred back into the pool. + */ +void +pcred_free(struct pcred *p); + +struct pcred * +pcred_alloc(void); + + LIST_HEAD(proclist, proc); /* A list of processes */ /* @@ -403,91 +419,143 @@ } #define curproc __curproc() -extern struct proc proc0; /* Process slot for swapper */ -extern int nprocs, maxproc; /* Current and max number of procs */ - -/* Process list lock; see kern_proc.c for locking protocol details */ -extern struct lock proclist_lock; - -extern struct proclist allproc; /* List of all processes */ -extern struct proclist zombproc; /* List of zombie processes */ - -extern SLIST_HEAD(deadprocs, proc) deadprocs; /* List of dead processes */ -extern struct simplelock deadproc_slock; +extern struct proc proc0; /* Process slot for swapper */ +extern int maxproc;/* Max number of procs (FIXME - instance) */ -extern struct proc *initproc; /* Process slots for init, pager */ +/* Forward declaration. */ +struct inst; -extern const struct proclist_desc proclists[]; +/* Return NULL if no process by that name found. */ +struct proc *p_find(struct inst *, pid_t, uint); +/* Return NULL if none found. */ +struct pgrp *pg_find(struct inst *, pid_t, uint); -extern struct pool pcred_pool; /* Memory pool for pcreds */ -extern struct pool plimit_pool; /* Memory pool for plimits */ -extern struct pool pstats_pool; /* memory pool for pstats */ -extern struct pool rusage_pool; /* Memory pool for rusages */ -extern struct pool ptimer_pool; /* Memory pool for ptimers */ - -struct proc *p_find(pid_t, uint); /* Find process by id */ -struct pgrp *pg_find(pid_t, uint); /* Find process group by id */ /* Flags values for p_find() and pg_find(). */ #define PFIND_ZOMBIE 1 /* look for zombies as well */ #define PFIND_LOCKED 2 /* proclist locked on entry */ #define PFIND_UNLOCK_FAIL 4 /* unlock proclist on failure */ #define PFIND_UNLOCK_OK 8 /* unlock proclist on success */ #define PFIND_UNLOCK (PFIND_UNLOCK_OK | PFIND_UNLOCK_FAIL) -/* For source compatibility. but UNLOCK_OK gives a stale answer... */ -#define pfind(pid) p_find((pid), PFIND_UNLOCK) -#define pgfind(pgid) pg_find((pgid), PFIND_UNLOCK) +#define pfind(inst, pid) \ + p_find((inst), (pid), PFIND_UNLOCK) + +#define pgfind(inst, pgid) \ + pg_find((inst), (pgid), PFIND_UNLOCK) + +/* Forward-declaration. */ struct simplelock; -int enterpgrp(struct proc *, pid_t, int); -void fixjobc(struct proc *, struct pgrp *, int); -int inferior(struct proc *, struct proc *); -int leavepgrp(struct proc *); -void sessdelete(struct session *); -void yield(void); -struct lwp *chooselwp(void); -void pgdelete(struct pgrp *); -void procinit(void); -void resetprocpriority(struct proc *); -void suspendsched(void); -int ltsleep(const void *, int, const char *, int, - __volatile struct simplelock *); -void wakeup(const void *); -void wakeup_one(const void *); -void exit1(struct lwp *, int); -int find_stopped_child(struct proc *, pid_t, int, struct proc **); -struct proc *proc_alloc(void); -void proc0_insert(struct proc *, struct lwp *, struct pgrp *, struct session *); -void proc_free(struct proc *); -void proc_free_mem(struct proc *); + +/* Move p to a new or existing process group (and session). If we are + * creating a new pgrp, the pgid should equal the calling process' pid. + * It's only valid to enter a process group that is in the session of + * the process. mksess should be set if we are creating a pgroup. */ +int enterpgrp(struct proc *, pid_t, int); + +/* Adjust pgrp jobc counters when specified process changes process + * group. We count the number of processes in each process gruop that + * "qualify" the group for terminal job control (those with a parent in + * a different process group of the same session). If that count + * reaches 0, the process group becomes orphaned. Check both the + * specified process' process group and that of its children. If ent is + * 0, p is leaving pgrp; if it's 1, it's entering. This must be called + * with the i_proclist_lock held. */ +void fixjobc(struct proc *, struct pgrp *, int); + +/* Is p below q in the process hierarchy? Returns 0 if not (or not in + * the same instance), 1 if they are (XXX - name misleading). */ +int inferior(struct proc *, struct proc *); + +/* If the process group is empty, also deletes the process group. */ +int leavepgrp(struct proc *); + +/* Delete a session (the session has no members). */ +void sessdelete(struct session *s); + +void yield(void); +struct lwp *chooselwp(void); +void pgdelete(struct pgrp *); +void resetprocpriority(struct proc *); +void suspendsched(void); +int ltsleep(const void *, int, const char *, int, + __volatile struct simplelock *); +void wakeup(const void *); +void wakeup_one(const void *); +void exit1(struct lwp *, int); +int find_stopped_child(struct proc *, pid_t, + int, struct proc **); + + +/* Allocate a process from within an instance. */ +struct proc *proc_alloc(struct inst *); + +/* + * Set entry for process 0 (init). + */ +void +proc0_insert(struct proc *p0, struct lwp *l0, + struct pgrp *pg0, struct session *s0); + + +/* + * Frees last resources of a process. Puts process back into available + * process pool. + */ +void +proc_free_mem(struct inst *i, struct proc *p); + + +void proc_free(struct proc *p); void exit_lwps(struct lwp *l); int fork1(struct lwp *, int, int, void *, size_t, - void (*)(void *), void *, register_t *, struct proc **); + void (*)(void *), void *, register_t *, + struct proc **); +int forkinst1(void (*)(void *), void *, const char *, + register_t *, struct proc **); void rqinit(void); int groupmember(gid_t, const struct ucred *); -int pgid_in_session(struct proc *, pid_t); + + +/* + * Check if process group pgid is in session of process p. Treats + * negative ids as process ids. Used to validate TIOCSPGRP requests. + * Returns EINVAL if pgid doesn't exist or EPERM if the sessions are + * invalid, or 0 on success. + */ +int +pgid_in_session(struct proc *p, pid_t pgid); + + #ifndef cpu_idle void cpu_idle(void); #endif -void cpu_exit(struct lwp *); + +/* + * Machdep routine to completely free up a lwp from an instance. + */ +void +cpu_exit(struct lwp *); + + void cpu_lwp_fork(struct lwp *, struct lwp *, void *, size_t, void (*)(void *), void *); #ifndef cpu_lwp_free void cpu_lwp_free(struct lwp *, int); #endif - void child_return(void *); - int proc_isunder(struct proc *, struct proc *); void proc_stop(struct proc *, int); -void proclist_lock_read(void); -void proclist_unlock_read(void); -int proclist_lock_write(void); -void proclist_unlock_write(int); -void p_sugid(struct proc *); -int proclist_foreach_call(struct proclist *, - int (*)(struct proc *, void *arg), void *); + +/* + * Mark a process as suid/sgid and reset some values (XXX) to their + * defaults. + */ +void +p_sugid(struct proc *p); + + static __inline struct proc *_proclist_skipmarker(struct proc *); static __inline struct proc * diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/ras.h mult-netbsd-3.1/sys/sys/ras.h --- NetBSD-3.1/sys/sys/ras.h 2004-07-19 04:12:31.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/ras.h 2007-11-11 13:27:03.000000000 +0000 @@ -55,7 +55,6 @@ #ifdef _KERNEL -struct pool; struct proc; caddr_t ras_lookup(struct proc *, caddr_t); @@ -63,8 +62,6 @@ int ras_fork(struct proc *, struct proc *); int ras_purgeall(struct proc *); -extern struct pool ras_pool; - #else #ifndef RAS_DECL diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/resourcevar.h mult-netbsd-3.1/sys/sys/resourcevar.h --- NetBSD-3.1/sys/sys/resourcevar.h 2005-02-03 19:20:02.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/resourcevar.h 2007-11-18 14:10:51.000000000 +0000 @@ -76,6 +76,7 @@ struct simplelock p_slock; /* mutex for p_refcnt */ }; + /* add user profiling from AST */ #define ADDUPROF(p) \ do { \ @@ -96,10 +97,12 @@ rlim_t ui_sbsize; /* socket buffer size */ }; -#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) -extern LIST_HEAD(uihashhead, uidinfo) *uihashtbl; -extern u_long uihash; /* size of hash table - 1 */ -int chgproccnt(uid_t, int); + + +LIST_HEAD(uihashhead, uidinfo); + + +int chgproccnt(struct inst *i, uid_t, int); int chgsbsize(uid_t, u_long *, u_long, rlim_t); extern char defcorename[]; @@ -107,11 +110,42 @@ void addupc_task(struct proc *, u_long, u_int); void calcru(struct proc *, struct timeval *, struct timeval *, struct timeval *); -struct plimit *limcopy(struct plimit *); -void limfree(struct plimit *); + + +/* + * Make a copy of the plimit structure. We share these structures + * copy-on-write after fork and copy when a limit has changed. XXX - + * should be limdup. + */ +struct plimit * +limcopy(struct plimit *lim); + + +/* + * Dereference a limit (and possibly put it back in the pool). + */ +void +limfree(struct plimit *lim); + + + void ruadd(struct rusage *, struct rusage *); -struct pstats *pstatscopy(struct pstats *); -void pstatsfree(struct pstats *); + + +/* + * Create a new pstats from an old. XXX - should be pstatsdup. + */ +struct pstats * +pstatscopy(struct pstats *ps); + + +/* + * Put a pstats back into the pool. + */ +void +pstatsfree(struct pstats *ps); + + extern rlim_t maxdmap; extern rlim_t maxsmap; #endif diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/savar.h mult-netbsd-3.1/sys/sys/savar.h --- NetBSD-3.1/sys/sys/savar.h 2005-10-21 18:39:40.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/savar.h 2007-11-13 18:31:33.000000000 +0000 @@ -69,6 +69,14 @@ union sau_state sau_interrupted; }; + +/* + * Global pool of supdata_upcall memory. + */ +extern struct pool +saupcall_pool; + + #define SAU_FLAG_DEFERRED_EVENT 0x1 #define SAU_FLAG_DEFERRED_INTERRUPTED 0x2 @@ -115,11 +123,6 @@ #define SA_FLAG_ALL SA_FLAG_PREEMPT -extern struct pool sadata_pool; /* memory pool for sadata structures */ -extern struct pool saupcall_pool; /* memory pool for pending upcalls */ -extern struct pool sastack_pool; /* memory pool for sastack structs */ -extern struct pool savp_pool; /* memory pool for sadata_vp structures */ - #ifdef _KERNEL #include diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/select.h mult-netbsd-3.1/sys/sys/select.h --- NetBSD-3.1/sys/sys/select.h 2005-03-19 13:23:15.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/select.h 2007-11-19 14:26:40.000000000 +0000 @@ -48,6 +48,7 @@ struct selinfo { struct klist sel_klist; /* knotes attached to this selinfo */ pid_t sel_pid; /* process to be notified */ + u_int sel_iid; /* process instance uuid */ uint8_t sel_collision; /* non-zero if a collision occurred */ }; #endif /* !_NETBSD_SOURCE_ */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/signalvar.h mult-netbsd-3.1/sys/sys/signalvar.h --- NetBSD-3.1/sys/sys/signalvar.h 2005-10-21 18:39:40.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/signalvar.h 2007-11-10 19:27:12.000000000 +0000 @@ -142,15 +142,58 @@ int coredump(struct lwp *, const char *); int coredump_netbsd(struct lwp *, struct vnode *, struct ucred *); void execsigs(struct proc *); -void gsignal(int, int); -void kgsignal(int, struct ksiginfo *, void *); + +/* + * See kgsignal(). + */ +void +gsignal(struct inst *i, int pgid, int signum); + +/* + * Delivers a signal specification to a process group in instance i. + */ +void +kgsignal(struct inst *i, int pgid, struct ksiginfo *ksi, void *data); + + +/* + * Calls through to kpgsignal(). See kpgsignal() for caveats. + */ +void +pgsignal(struct pgrp *pgrp, int sig, int checktty); + + +/* + * Deliver a signal to a process group. This DOES NOT check for + * instance correctness (there's no "caller"). If checktty is 1, limit + * to members who have a controlling terminal. + */ +void +kpgsignal(struct pgrp *pgrp, struct ksiginfo *ks, + void *data, int checktty); + + int issignal(struct lwp *); -void pgsignal(struct pgrp *, int, int); -void kpgsignal(struct pgrp *, struct ksiginfo *, void *, int); void postsig(int); void psignal1(struct proc *, int, int); -void kpsignal1(struct proc *, struct ksiginfo *, void *, int); -#define kpsignal(p, ksi, data) kpsignal1((p), (ksi), (data), 1) + + +/* + * This delivers a signal to a process. Note that this DOES NOT check + * for instance correctness (there's no "caller"). + */ +void +kpsignal1(struct proc *p, struct ksiginfo *ks, void *data, int dolock); + + +/* + * Calls through to kpsignal1() and requests locking. See kpsignal1() + * for caveats. + */ +#define kpsignal(p, ksi, data) \ + kpsignal1((p), (ksi), (data), 1) + + #define psignal(p, sig) psignal1((p), (sig), 1) #define sched_psignal(p, sig) psignal1((p), (sig), 0) void siginit(struct proc *); @@ -158,7 +201,16 @@ void sigexit(struct lwp *, int); void killproc(struct proc *, const char *); void setsigvec(struct proc *, int, struct sigaction *); -int killpg1(struct proc *, struct ksiginfo *, int, int); + + +/* + * Common code for process, group, or broadcast kill. cp is the calling + * process. + */ +int +killpg1(struct proc *cp, struct ksiginfo *ks, int pgid, int all); + + struct lwp *proc_unstop(struct proc *p); int sigaction1(struct proc *, int, const struct sigaction *, diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/socketvar.h mult-netbsd-3.1/sys/sys/socketvar.h --- NetBSD-3.1/sys/sys/socketvar.h 2004-09-03 19:14:09.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/socketvar.h 2007-11-15 14:48:25.000000000 +0000 @@ -131,6 +131,7 @@ struct mbuf **, int *); struct mowner *so_mowner; /* who owns mbufs for this socket */ uid_t so_uid; /* who opened the socket */ + struct inst *so_inst; /* ...and from which instance */ }; #define SB_EMPTY_FIXUP(sb) \ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/syscall.h mult-netbsd-3.1/sys/sys/syscall.h --- NetBSD-3.1/sys/sys/syscall.h 2005-02-27 00:03:25.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/syscall.h 2007-11-15 13:34:52.000000000 +0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.h,v 1.156 2005/02/27 00:03:25 perry Exp $ */ +/* $NetBSD$ */ /* * System call numbers. @@ -1025,5 +1025,8 @@ /* syscall: "pollts" ret: "int" args: "struct pollfd *" "u_int" "const struct timespec *" "const sigset_t *" */ #define SYS_pollts 374 -#define SYS_MAXSYSCALL 375 +/* syscall: "instctl" ret: "int" args: "struct instctl *" */ +#define SYS_instctl 375 + +#define SYS_MAXSYSCALL 376 #define SYS_NSYSENT 512 diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/syscallargs.h mult-netbsd-3.1/sys/sys/syscallargs.h --- NetBSD-3.1/sys/sys/syscallargs.h 2005-02-27 00:03:25.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/syscallargs.h 2007-11-15 13:34:52.000000000 +0000 @@ -1,4 +1,4 @@ -/* $NetBSD: syscallargs.h,v 1.138 2005/02/27 00:03:25 perry Exp $ */ +/* $NetBSD$ */ /* * System call argument lists. @@ -1588,6 +1588,10 @@ syscallarg(const sigset_t *) mask; }; +struct sys_instctl_args { + syscallarg(struct instctl *) ctl; +}; + /* * System call prototypes. */ @@ -2251,4 +2255,6 @@ int sys_pollts(struct lwp *, void *, register_t *); +int sys_instctl(struct lwp *, void *, register_t *); + #endif /* _SYS__SYSCALLARGS_H_ */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/sysctl.h mult-netbsd-3.1/sys/sys/sysctl.h --- NetBSD-3.1/sys/sys/sysctl.h 2005-06-10 16:10:51.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/sysctl.h 2007-12-17 11:11:39.000000000 +0000 @@ -269,7 +269,11 @@ #define KERN_BUF 76 /* struct: buffers */ #define KERN_FILE2 77 /* struct: file entries */ #define KERN_VERIEXEC 78 /* node: verified exec */ -#define KERN_MAXID 79 /* number of valid kern ids */ +#define KERN_INST 79 /* struct: instance entries */ +#define KERN_PROC2_INST 80 /* struct: instance process entries */ +#define KERN_LWP_INST 81 /* struct: instance lwp entries */ +#define KERN_PROC_ARGS_INST 82 /* struct: instance process argv/env */ +#define KERN_MAXID 83 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ @@ -368,6 +372,12 @@ #define KERN_PROC_RGID 8 /* by real gid */ /* + * KERN_INST subtypes. + */ +#define KERN_INST_ALL 0 /* Everything. */ +#define KERN_INST_CUR 1 /* The current instance. */ + +/* * KERN_PROC_TTY sub-subtypes */ #define KERN_PROC_TTY_NODEV NODEV /* no controlling tty */ @@ -429,6 +439,21 @@ u_int32_t __bits[4]; } ki_sigset_t; + +struct kinfo_inst { + u_int32_t i_uuid; + u_int32_t i_refcnt; + u_int32_t i_state; + char i_host[MAXHOSTNAMELEN]; + char i_domain[MAXHOSTNAMELEN]; + u_int32_t i_nprocs; + u_int32_t i_nfiles; + u_int32_t i_nsocks; + u_int32_t i_npipes; + u_int32_t i_ncreds; + u_int32_t i_nsess; +}; + struct kinfo_proc2 { u_int64_t p_forw; /* PTR: linked run/sleep queue. */ u_int64_t p_back; diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/systrace.h mult-netbsd-3.1/sys/sys/systrace.h --- NetBSD-3.1/sys/sys/systrace.h 2006-10-16 21:36:50.000000000 +0100 +++ mult-netbsd-3.1/sys/sys/systrace.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,222 +0,0 @@ -/* $NetBSD: systrace.h,v 1.12.14.3 2006/10/16 20:36:50 ghen Exp $ */ - -/* - * Copyright 2002 Niels Provos - * 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 Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -#ifndef _SYSTRACE_H_ -#define _SYSTRACE_H_ - -#include -#include -#include - -#define SYSTR_EMULEN 8 /* sync with sys proc */ - -struct str_msg_emul { - char emul[SYSTR_EMULEN]; -}; - -struct str_msg_ugid { - uid_t uid; - gid_t gid; -}; - -#define SYSTR_MAX_POLICIES 64 -#define SYSTR_MAXARGS 64 -#define SYSTR_MAXFNAME 8 -#define SYSTR_MAXREPLEN 2048 - -struct str_msg_ask { - int32_t code; - int32_t argsize; - register_t args[SYSTR_MAXARGS]; - register_t rval[2]; - int32_t result; -}; - -/* Queued on fork or exit of a process */ - -struct str_msg_child { - pid_t new_pid; -}; - -#define SYSTR_MSG_ASK 1 -#define SYSTR_MSG_RES 2 -#define SYSTR_MSG_EMUL 3 -#define SYSTR_MSG_CHILD 4 -#define SYSTR_MSG_UGID 5 -#define SYSTR_MSG_POLICYFREE 6 - -#define SYSTR_MSG_NOPROCESS(x) \ - ((x)->msg.msg_type == SYSTR_MSG_CHILD || \ - (x)->msg.msg_type == SYSTR_MSG_POLICYFREE) - -struct str_message { - int32_t msg_type; - pid_t msg_pid; - u_int16_t msg_seqnr; /* answer has to match seqnr */ - int16_t msg_policy; - union { - struct str_msg_emul msg_emul; - struct str_msg_ugid msg_ugid; - struct str_msg_ask msg_ask; - struct str_msg_child msg_child; - } msg_data; -}; - -struct str_process; -struct str_msgcontainer { - TAILQ_ENTRY(str_msgcontainer) next; - struct str_process *strp; - - struct str_message msg; -}; - - -struct systrace_answer { - pid_t stra_pid; - u_int16_t stra_seqnr; - int16_t reserved; - uid_t stra_seteuid; /* elevated privileges for system call */ - uid_t stra_setegid; - int32_t stra_policy; - int32_t stra_error; - int32_t stra_flags; -}; - -#define SYSTR_READ 1 -#define SYSTR_WRITE 2 - -struct systrace_io { - pid_t strio_pid; - int32_t strio_op; - void *strio_offs; - void *strio_addr; - size_t strio_len; -}; - -#define SYSTR_POLICY_NEW 1 -#define SYSTR_POLICY_ASSIGN 2 -#define SYSTR_POLICY_MODIFY 3 - -struct systrace_policy { - int32_t strp_op; - int32_t strp_num; - union { - struct { - int16_t code; - int16_t policy; - } assign; - pid_t pid; - int32_t maxents; - } strp_data; -}; - -#define strp_pid strp_data.pid -#define strp_maxents strp_data.maxents -#define strp_code strp_data.assign.code -#define strp_policy strp_data.assign.policy - -#define SYSTR_NOLINKS 1 - -struct systrace_replace { - pid_t strr_pid; - u_int16_t strr_seqnr; - int16_t reserved; - int32_t strr_nrepl; - caddr_t strr_base; /* Base memory */ - size_t strr_len; /* Length of memory */ - int32_t strr_argind[SYSTR_MAXARGS]; - size_t strr_off[SYSTR_MAXARGS]; - size_t strr_offlen[SYSTR_MAXARGS]; - int32_t strr_flags[SYSTR_MAXARGS]; -}; - -#define STRIOCATTACH _IOW('s', 101, pid_t) -#define STRIOCDETACH _IOW('s', 102, pid_t) -#define STRIOCANSWER _IOW('s', 103, struct systrace_answer) -#define STRIOCIO _IOWR('s', 104, struct systrace_io) -#define STRIOCPOLICY _IOWR('s', 105, struct systrace_policy) -#define STRIOCGETCWD _IOW('s', 106, pid_t) -#define STRIOCRESCWD _IO('s', 107) -#define STRIOCREPORT _IOW('s', 108, pid_t) -#define STRIOCREPLACE _IOW('s', 109, struct systrace_replace) - -#define SYSTR_POLICY_ASK 0 -#define SYSTR_POLICY_PERMIT 1 -#define SYSTR_POLICY_NEVER 2 - -#define SYSTR_FLAGS_RESULT 0x001 -#define SYSTR_FLAGS_SETEUID 0x002 -#define SYSTR_FLAGS_SETEGID 0x004 - -#ifdef _KERNEL -#include - -/* XXX: these shouldn't be here. */ -#define SET(t, f) ((t) |= (f)) -#define ISSET(t, f) ((t) & (f)) -#define CLR(t, f) ((t) &= ~(f)) - -struct fsystrace { - struct lock lock; - struct selinfo si; - - TAILQ_HEAD(strprocessq, str_process) processes; - size_t nprocesses; - - TAILQ_HEAD(strpolicyq, str_policy) policies; - - TAILQ_HEAD(strmessageq, str_msgcontainer) messages; - - size_t npolicynr; - size_t npolicies; - - int issuser; - uid_t p_ruid; - gid_t p_rgid; - - /* cwd magic */ - pid_t fd_pid; - struct vnode *fd_cdir; - struct vnode *fd_rdir; -}; - -/* Internal prototypes */ - -int systrace_enter(struct proc *, register_t, void *); -void systrace_namei(struct nameidata *); -void systrace_exit(struct proc *, register_t, void *, register_t [], int); -void systrace_sys_exit(struct proc *); -void systrace_sys_fork(struct proc *, struct proc *); -void systrace_init(void); - -#endif /* _KERNEL */ -#endif /* !_SYSTRACE_H_ */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/time.h mult-netbsd-3.1/sys/sys/time.h --- NetBSD-3.1/sys/sys/time.h 2005-02-26 22:25:34.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/time.h 2007-11-13 18:31:33.000000000 +0000 @@ -192,6 +192,11 @@ struct proc *pt_proc; }; + +extern struct pool +ptimer_pool; + + #define pt_ch pt_data.pt_ch #define pt_list pt_data.pt_nonreal.pt_list #define pt_active pt_data.pt_nonreal.pt_active diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/tprintf.h mult-netbsd-3.1/sys/sys/tprintf.h --- NetBSD-3.1/sys/sys/tprintf.h 2005-02-03 19:20:02.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/tprintf.h 2007-11-12 16:59:26.000000000 +0000 @@ -34,14 +34,38 @@ #ifndef _SYS_TPRINF_H_ #define _SYS_TPRINF_H_ +/* + * Note that all of these are documented in the kernel manual pages; + * what follows are minimal explanations. + */ + #ifdef _KERNEL + typedef struct session *tpr_t; -tpr_t tprintf_open(struct proc *); -void tprintf_close(tpr_t); +/* + * Open a channel to the process's (session's) terminal. This holds a + * reference to both the session and the instance. Returns NULL if the + * process cannot be printed to. + */ +tpr_t +tprintf_open(struct proc *); + + +/* + * Close a channel opened with tprintf_open(). + */ +void +tprintf_close(tpr_t); + + +/* + * Write to a channel opened with tprintf_open(). + */ +void +tprintf(tpr_t, const char *fmt, ...) + __attribute__((__format__(__printf__,2,3))); -void tprintf(tpr_t, const char *fmt, ...) - __attribute__((__format__(__printf__,2,3))); #endif /* _KERNEL */ #endif /* _SYS_TPRINF_H_ */ diff -r -u -N --exclude CVS NetBSD-3.1/sys/sys/ucred.h mult-netbsd-3.1/sys/sys/ucred.h --- NetBSD-3.1/sys/sys/ucred.h 2005-02-26 22:25:34.000000000 +0000 +++ mult-netbsd-3.1/sys/sys/ucred.h 2007-11-23 10:17:20.000000000 +0000 @@ -49,6 +49,9 @@ gid_t cr_groups[NGROUPS]; /* groups */ }; +/* Forward declaration. */ +struct inst; + struct ucred { struct simplelock cr_lock; /* mutex for ref count */ u_int32_t cr_ref; /* reference count */ @@ -57,6 +60,7 @@ gid_t cr_gid; /* effective group id */ u_int32_t cr_ngroups; /* number of groups */ gid_t cr_groups[NGROUPS]; /* groups */ + struct inst *cr_inst; }; #define NOCRED ((struct ucred *)-1) /* no credential available */ @@ -86,8 +90,9 @@ struct ucred *crcopy(struct ucred *); struct ucred *crdup(const struct ucred *); +struct ucred *crdupinst(const struct ucred *); void crfree(struct ucred *); -struct ucred *crget(void); +struct ucred *crget(struct inst *); int suser(const struct ucred *, u_short *); void crcvt(struct ucred *, const struct uucred *); int crcmp(const struct ucred *, const struct uucred *); diff -r -u -N --exclude CVS NetBSD-3.1/sys/ufs/ufs/ufs_quota.c mult-netbsd-3.1/sys/ufs/ufs/ufs_quota.c --- NetBSD-3.1/sys/ufs/ufs/ufs_quota.c 2005-02-26 22:32:20.000000000 +0000 +++ mult-netbsd-3.1/sys/ufs/ufs/ufs_quota.c 2007-11-18 14:10:51.000000000 +0000 @@ -388,6 +388,7 @@ * Save the credential of the process that turned on quotas. * Set up the time limits for this quota. */ + /* FIXME - instances */ crhold(p->p_ucred); ump->um_cred[type] = p->p_ucred; ump->um_btime[type] = MAX_DQ_TIME; diff -r -u -N --exclude CVS NetBSD-3.1/sys/uvm/uvm_glue.c mult-netbsd-3.1/sys/uvm/uvm_glue.c --- NetBSD-3.1/sys/uvm/uvm_glue.c 2005-12-06 20:00:12.000000000 +0000 +++ mult-netbsd-3.1/sys/uvm/uvm_glue.c 2007-11-23 10:17:20.000000000 +0000 @@ -83,6 +83,7 @@ #include #include #include +#include #include @@ -375,8 +376,7 @@ */ void -uvm_proc_exit(p) - struct proc *p; +uvm_proc_exit(struct proc *p) { struct lwp *l = curlwp; /* XXX */ struct vmspace *ovm; @@ -479,11 +479,11 @@ */ void -uvm_scheduler() +uvm_scheduler(void) { - struct lwp *l, *ll; - int pri; - int ppri; + struct lwp *l, *ll; + struct inst *i; + int pri, ppri; loop: #ifdef DEBUG @@ -491,30 +491,39 @@ tsleep(&proc0, PVM, "noswap", 0); #endif ll = NULL; /* process to choose */ - ppri = INT_MIN; /* its priority */ - proclist_lock_read(); + ppri = INT_MIN; /* its priority */ + + instlist_lock_read(); - LIST_FOREACH(l, &alllwp, l_list) { - /* is it a runnable swapped out process? */ - if (l->l_stat == LSRUN && (l->l_flag & L_INMEM) == 0) { - pri = l->l_swtime + l->l_slptime - - (l->l_proc->p_nice - NZERO) * 8; - if (pri > ppri) { /* higher priority? remember it. */ - ll = l; - ppri = pri; + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + /* is it a runnable swapped out process? */ + if (l->l_stat == LSRUN && + (l->l_flag & L_INMEM) == 0) { + pri = l->l_swtime + l->l_slptime - + (l->l_proc->p_nice - NZERO) * 8; + if (pri > ppri) { + ll = l; + ppri = pri; + } } } + proclist_unlock_read(i); } + instlist_unlock_read(); + /* * XXXSMP: possible unlock/sleep race between here and the * "scheduler" tsleep below.. */ - proclist_unlock_read(); + #ifdef DEBUG if (swapdebug & SDB_FOLLOW) printf("scheduler: running, procp %p pri %d\n", ll, ppri); #endif + /* * Nothing to do, back to sleep */ @@ -524,29 +533,35 @@ } /* - * we have found swapped out process which we would like to bring - * back in. + * we have found swapped out process which we would like to + * bring back in. * - * XXX: this part is really bogus cuz we could deadlock on memory - * despite our feeble check + * XXX: this part is really bogus cuz we could deadlock on + * memory despite our feeble check */ if (uvmexp.free > atop(USPACE)) { #ifdef DEBUG if (swapdebug & SDB_SWAPIN) - printf("swapin: pid %d(%s)@%p, pri %d free %d\n", - l->l_proc->p_pid, l->l_proc->p_comm, l->l_addr, ppri, uvmexp.free); + printf("swapin: pid %d(%s)@%p, iid %d pri %d " + "free %d\n", l->l_proc->p_pid, + l->l_proc->p_comm, l->l_addr, + l->l_inst->i_uuid, ppri, + uvmexp.free); #endif uvm_swapin(l); goto loop; } + /* - * not enough memory, jab the pageout daemon and wait til the coast - * is clear + * not enough memory, jab the pageout daemon and wait til the coast is + * clear */ #ifdef DEBUG if (swapdebug & SDB_FOLLOW) - printf("scheduler: no room for pid %d(%s), free %d\n", - l->l_proc->p_pid, l->l_proc->p_comm, uvmexp.free); + printf("scheduler: no room for pid %d(%s), iid %d, " + "free %d\n", l->l_proc->p_pid, + l->l_proc->p_comm, l->l_inst->i_uuid, + uvmexp.free); #endif uvm_wait("schedpwait"); #ifdef DEBUG @@ -556,10 +571,10 @@ goto loop; } + /* * swappable: is LWP "l" swappable? */ - #define swappable(l) \ (((l)->l_flag & (L_INMEM)) && \ ((((l)->l_proc->p_flag) & (P_SYSTEM | P_WEXIT)) == 0) && \ @@ -575,17 +590,18 @@ * are swapped... otherwise the longest-sleeping or stopped process * is swapped, otherwise the longest resident process... */ - void uvm_swapout_threads() { - struct lwp *l; - struct lwp *outl, *outl2; - int outpri, outpri2; - int didswap = 0; - extern int maxslp; + struct lwp *l, *outl, *outl2; + int outpri, outpri2, didswap; + struct inst *i; + + extern int maxslp; /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */ + didswap = 0; + #ifdef DEBUG if (!enableswap) return; @@ -597,54 +613,61 @@ */ outl = outl2 = NULL; outpri = outpri2 = 0; - proclist_lock_read(); - LIST_FOREACH(l, &alllwp, l_list) { - KASSERT(l->l_proc != NULL); - if (!swappable(l)) - continue; - switch (l->l_stat) { - case LSONPROC: - continue; - - case LSRUN: - if (l->l_swtime > outpri2) { - outl2 = l; - outpri2 = l->l_swtime; - } - continue; - case LSSLEEP: - case LSSTOP: - if (l->l_slptime >= maxslp) { - uvm_swapout(l); - didswap++; - } else if (l->l_slptime > outpri) { - outl = l; - outpri = l->l_slptime; + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + KASSERT(l->l_proc != NULL); + if (!swappable(l)) + continue; + switch (l->l_stat) { + case LSONPROC: + continue; + + case LSRUN: + if (l->l_swtime > outpri2) { + outl2 = l; + outpri2 = l->l_swtime; + } + continue; + + case LSSLEEP: + case LSSTOP: + if (l->l_slptime >= maxslp) { + uvm_swapout(l); + didswap++; + } else if (l->l_slptime > outpri) { + outl = l; + outpri = l->l_slptime; + } + continue; } - continue; } + proclist_unlock_read(i); } - proclist_unlock_read(); + instlist_unlock_read(); /* * If we didn't get rid of any real duds, toss out the next most - * likely sleeping/stopped or running candidate. We only do this - * if we are real low on memory since we don't gain much by doing - * it (USPACE bytes). + * likely sleeping/stopped or running candidate. We only do + * this if we are real low on memory since we don't gain much by + * doing it (USPACE bytes). */ if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) { if ((l = outl) == NULL) l = outl2; #ifdef DEBUG if (swapdebug & SDB_SWAPOUT) - printf("swapout_threads: no duds, try procp %p\n", l); + printf("swapout_threads: no duds, " + "try procp %p\n", l); #endif if (l) uvm_swapout(l); } } + /* * uvm_swapout: swap out lwp "l" * @@ -652,10 +675,8 @@ * the pmap. * - XXXCDC: should deactivate all process' private anonymous memory */ - static void -uvm_swapout(l) - struct lwp *l; +uvm_swapout(struct lwp *l) { vaddr_t addr; int s; @@ -699,11 +720,11 @@ pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); } + /* * uvm_coredump_walkmap: walk a process's map for the purpose of dumping * a core file. */ - int uvm_coredump_walkmap(p, vp, cred, func, cookie) struct proc *p; diff -r -u -N --exclude CVS NetBSD-3.1/sys/uvm/uvm_meter.c mult-netbsd-3.1/sys/uvm/uvm_meter.c --- NetBSD-3.1/sys/uvm/uvm_meter.c 2004-10-10 10:57:31.000000000 +0100 +++ mult-netbsd-3.1/sys/uvm/uvm_meter.c 2007-11-23 10:17:20.000000000 +0000 @@ -49,6 +49,7 @@ #include #include #include +#include /* * maxslp: ???? XXXCDC @@ -92,27 +93,32 @@ * 1, 5, and 15 minute internvals. */ static void -uvm_loadav(avg) - struct loadavg *avg; +uvm_loadav(struct loadavg *avg) { - int i, nrun; - struct lwp *l; + int i, nrun; + struct lwp *l; + struct inst *inst; - proclist_lock_read(); nrun = 0; - LIST_FOREACH(l, &alllwp, l_list) { - switch (l->l_stat) { - case LSSLEEP: - if (l->l_priority > PZERO || l->l_slptime > 1) - continue; - /* fall through */ - case LSRUN: - case LSONPROC: - case LSIDL: - nrun++; + instlist_lock_read(); + LIST_FOREACH(inst, &allinst, i_list) { + proclist_lock_read(inst); + LIST_FOREACH(l, &inst->i_alllwp, l_list) { + switch (l->l_stat) { + case LSSLEEP: + if (l->l_priority > PZERO || l->l_slptime > 1) + continue; + /* fall through */ + case LSRUN: + case LSONPROC: + case LSIDL: + nrun++; + } } + proclist_unlock_read(inst); } - proclist_unlock_read(); + instlist_unlock_read(); + for (i = 0; i < 3; i++) avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; @@ -417,10 +423,10 @@ * uvm_total: calculate the current state of the system. */ static void -uvm_total(totalp) - struct vmtotal *totalp; +uvm_total(struct vmtotal *totalp) { - struct lwp *l; + struct lwp *l; + struct inst *i; #if 0 struct vm_map_entry * entry; struct vm_map *map; @@ -432,62 +438,43 @@ /* * calculate process statistics */ - - proclist_lock_read(); - LIST_FOREACH(l, &alllwp, l_list) { - if (l->l_proc->p_flag & P_SYSTEM) - continue; - switch (l->l_stat) { - case 0: - continue; - - case LSSLEEP: - case LSSTOP: - if (l->l_flag & L_INMEM) { - if (l->l_priority <= PZERO) - totalp->t_dw++; - else if (l->l_slptime < maxslp) - totalp->t_sl++; - } else if (l->l_slptime < maxslp) - totalp->t_sw++; - if (l->l_slptime >= maxslp) + instlist_lock_read(); + LIST_FOREACH(i, &allinst, i_list) { + proclist_lock_read(i); + LIST_FOREACH(l, &i->i_alllwp, l_list) { + if (l->l_proc->p_flag & P_SYSTEM) continue; - break; - - case LSRUN: - case LSONPROC: - case LSIDL: - if (l->l_flag & L_INMEM) - totalp->t_rq++; - else - totalp->t_sw++; - if (l->l_stat == LSIDL) + switch (l->l_stat) { + case 0: continue; - break; + case LSSLEEP: + case LSSTOP: + if (l->l_flag & L_INMEM) { + if (l->l_priority <= PZERO) + totalp->t_dw++; + else if (l->l_slptime < maxslp) + totalp->t_sl++; + } else if (l->l_slptime < maxslp) + totalp->t_sw++; + if (l->l_slptime >= maxslp) + continue; + break; + case LSRUN: + case LSONPROC: + case LSIDL: + if (l->l_flag & L_INMEM) + totalp->t_rq++; + else + totalp->t_sw++; + if (l->l_stat == LSIDL) + continue; + break; + } } - /* - * note active objects - */ -#if 0 - /* - * XXXCDC: BOGUS! rethink this. in the mean time - * don't do it. - */ - paging = 0; - vm_map_lock(map); - for (map = &p->p_vmspace->vm_map, entry = map->header.next; - entry != &map->header; entry = entry->next) { - if (entry->is_a_map || entry->is_sub_map || - entry->object.uvm_obj == NULL) - continue; - /* XXX how to do this with uvm */ - } - vm_map_unlock(map); - if (paging) - totalp->t_pw++; -#endif + proclist_unlock_read(i); } - proclist_unlock_read(); + instlist_unlock_read(); + /* * Calculate object memory usage statistics. */