GENERIC from Wed Feb 17 11:13:48 2010 +0200, vm6 0b84114, vmcore.421 KDB: debugger backends: ddb KDB: current backend: ddb 524288K of memory above 4GB ignored Copyright (c) 1992-2010 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 9.0-CURRENT #0 r203990+0b84114: Wed Feb 17 21:43:15 CET 2010 pho@x4.osted.lan:/var/tmp/deviant2/sys/i386/compile/BENCH i386 Timecounter "i8254" frequency 1193182 Hz quality 0 CPU: AMD Phenom(tm) 9150e Quad-Core Processor (1799.99-MHz 686-class CPU) Origin = "AuthenticAMD" Id = 0x100f23 Stepping = 3 Features=0x178bfbff Features2=0x802009 AMD Features=0xee500800 AMD Features2=0x7ff TSC: P-state invariant real memory = 4294967296 (4096 MB) avail memory = 3536830464 (3372 MB) : Trying to mount root from ufs:/dev/ad4s1a Enter full pathname of shell or RETURN for /bin/sh: # mount -t ufs -a # swapon -a swapon: adding /dev/ad4s1b as swap device swapon: adding /dev/ad4s2b as swap device # cd ~pho/stress2/misc # sysctl vfs.vmio vfs.vmio.writed_act: 0 vfs.vmio.writed_inact: 0 vfs.vmio.writed_wakeups: 0 vfs.vmio.max_writedirty: 216201 vfs.vmio.writedirty: 0 vfs.vmio.alloc_wait: 0 vfs.vmio.reserv_used: 0 vfs.vmio.getpages_write: 0 vfs.vmio.getpages_read: 19 vfs.vmio.rollbacks2: 0 vfs.vmio.rollbacks1: 0 vfs.vmio.write_pack: 16 vfs.vmio.read_pack: 16 vfs.vmio.clrbuf: 1 vfs.vmio.run: 0 # sysctl vfs.vmio.run=1 vfs.vmio.run: 0 -> 1 # ./f.sh f10 Total 4656 data blocks, 156 breaks, 3.35% fragmentation. Total 4656 data blocks, 156 breaks, 3.35% fragmentation. Total 4656 data blocks, 158 breaks, 3.39% fragmentation. Total 4656 data blocks, 157 breaks, 3.37% fragmentation. Total 4656 data blocks, 169 breaks, 3.63% fragmentation. Total 4656 data blocks, 183 breaks, 3.93% fragmentation. Total 4656 data blocks, 158 breaks, 3.39% fragmentation. Total 4656 data blocks, 155 breaks, 3.33% fragmentation. Total 4656 data blocks, 159 breaks, 3.41% fragmentation. Total 4656 data blocks, 155 breaks, 3.33% fragmentation. f12 umount: unmount of /mnt failed: Device busy Total 4656 data blocks, 164 breaks, 3.52% fragmentation. Total 4656 data blocks, 183 breaks, 3.93% fragmentation. Total 4656 data blocks, 188 breaks, 4.04% fragmentation. Total 4656 data blocks, 201 breaks, 4.32% fragmentation. Total 4656 data blocks, 171 breaks, 3.67% fragmentation. Total 4656 data blocks, 182 breaks, 3.91% fragmentation. Total 4656 data blocks, 174 breaks, 3.74% fragmentation. Total 4656 data blocks, 166 breaks, 3.57% fragmentation. Total 4656 data blocks, 159 breaks, 3.41% fragmentation. Total 4656 data blocks, 154 breaks, 3.31% fragmentation. # exit Entropy harvesting: interrupts ethernet point_to_point kickstart. Fast boot: skipping disk checks. Additional TCP/IP options: rfc1323 extensions=NO no-ipv4-mapped-ipv6. re0: link state changed to DOWN Starting Network: lo0 re0 fwe0 fwip0. Starting Network: fwe0. Starting Network: fwip0. add net default: gateway 192.168.1.1 add net ::ffff:0.0.0.0: gateway ::1 add net ::0.0.0.0: gateway ::1 add net fe80::: gateway ::1 add net ff02::: gateway ::1 Additional ABI support: linux Fatal trap 12: page fault while in kernel mode cpuid = 0; apic id = 00 fault virtual address = 0xd0aaacd7 fault code = supervisor write, page not present instruction pointer = 0x20:0xc517dae0 stack pointer = 0x28:0xf611e7ac frame pointer = 0x28:0xf611e7c0 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, def32 1, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 49890 (kldload) [ thread pid 49890 tid 100096 ] Stopped at 0xc517dae0: subb %ah,0xda98c517(%ebp) db> ru pho db:0:pho> bt Tracing pid 49890 tid 100096 td 0xc750f240 _end(c517a528,f611e868,f611e874,1,f611e878,...) at 0xc517dae0 vnode_pager_read(c78d27c4,f611e8f4,8,c4de1cf0,7,...) at vnode_pager_read+0x339 vn_read_chunk(c78d27c4,f611e8f4,c6d63380,c6d63380,8,...) at vn_read_chunk+0xec vn_rdwr(0,c78d27c4,c9c0a000,22fe0,0,...) at vn_rdwr+0x189 link_elf_load_file(c0d9f760,c92cda40,f611ec14,c750f240,0,...) at link_elf_load_file+0x4a3 linker_load_module(0,f611ec48,2,f611ec58,c088fb46,...) at linker_load_module+0x8f7 kern_kldload(c750f240,c70c6000,f611ec70,0,bfbfe950,...) at kern_kldload+0xec kldload(c750f240,f611ecf8,c,c750f240,f611ed2c,...) at kldload+0x74 syscall(f611ed38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (304, FreeBSD ELF32, kldload), eip = 0x280d75db, esp = 0xbfbfe94c, ebp = 0xbfbfee38 --- db:0:bt> show allpcpu Current CPU: 0 cpuid = 0 dynamic pcpu = 0x653800 curthread = 0xc750f240: pid 49890 "kldload" curpcb = 0xf611ed90 fpcurthread = none idlethread = 0xc6d5f480: pid 11 "idle: cpu0" APIC ID = 0 currentldt = 0x50 cpuid = 1 dynamic pcpu = 0x5d38800 curthread = 0xc6d5f6c0: pid 11 "idle: cpu1" curpcb = 0xc6b30d90 fpcurthread = none idlethread = 0xc6d5f6c0: pid 11 "idle: cpu1" APIC ID = 1 currentldt = 0x50 cpuid = 2 dynamic pcpu = 0x5d3b800 curthread = 0xc6d5f900: pid 11 "idle: cpu2" curpcb = 0xc6b2dd90 fpcurthread = none idlethread = 0xc6d5f900: pid 11 "idle: cpu2" APIC ID = 2 currentldt = 0x50 cpuid = 3 dynamic pcpu = 0x5d3e800 curthread = 0xc6d5fb40: pid 11 "idle: cpu3" curpcb = 0xc6b2ad90 fpcurthread = none idlethread = 0xc6d5fb40: pid 11 "idle: cpu3" APIC ID = 3 currentldt = 0x50 db:0:allpcpu> show alllocks No such command db:0:alllocks> show lockedvnods Locked vnodes 0xc78d27c4: tag ufs, type VREG usecount 1, writecount 0, refcount 2 mountedhere 0 flags () v_object 0xc99a2220 ref 0 pages 40 lock type ufs: SHARED (count 1) ino 167135, on dev ad4s1a db:0:lockedvnods> show mount 0xc7345ca8 /dev/ad4s1a on / (ufs) 0xc7346000 devfs on /dev (devfs) 0xc73d6510 /dev/ad4s1e on /tmp (ufs) 0xc73d6288 /dev/ad4s1f on /usr (ufs) 0xc73d6000 /dev/ad4s1d on /var (ufs) 0xc9ae8798 procfs on /proc (procfs) More info: show mount db:0:mount> ps pid ppid pgrp uid state wmesg wchan cmd 49890 49887 49029 0 R+ CPU 0 kldload 49887 49029 49029 0 S+ wait 0xc7a1f2a8 sh 49882 1 49882 0 Ss select 0xc9a6ada4 syslogd 49700 1 49700 0 Ss select 0xc6fd9ca4 devd 49029 1 49029 0 Ss+ wait 0xc7ece000 sh 21 0 0 0 DL flowclea 0xc0e19fa8 [flowcleaner] 20 0 0 0 DL sdflush 0xc0e25700 [softdepflush] 19 0 0 0 DL vlruwt 0xc733c550 [vnlru] 18 0 0 0 DL syncer 0xc0e19db4 [syncer] 17 0 0 0 DL psleep 0xc0e19ae8 [bufdaemon] 16 0 0 0 DL pgzero 0xc0e2655c [pagezero] 15 0 0 0 DL psleep 0xc0e26144 [vmdaemon] 9 0 0 0 DL writed 0xc0e26524 [writed] 8 0 0 0 DL psleep 0xc0e2610c [pagedaemon] 7 0 0 0 DL ccb_scan 0xc0dd24d4 [xpt_thrd] 6 0 0 0 DL - 0xc70cfc3c [fdc0] 5 0 0 0 SL - 0xc6fdb000 [fw0_probe] 14 0 0 0 DL (threaded) [usb] 100057 D - 0xc6fb4d0c [usbus5] 100056 D - 0xc6fb4cdc [usbus5] 100055 D - 0xc6fb4cac [usbus5] 100054 D - 0xc6fb4c7c [usbus5] 100052 D - 0xc6faab5c [usbus4] 100051 D - 0xc6faab2c [usbus4] 100050 D - 0xc6faaafc [usbus4] 100049 D - 0xc6faaacc [usbus4] 100048 D - 0xc6fa6b5c [usbus3] 100047 D - 0xc6fa6b2c [usbus3] 100046 D - 0xc6fa6afc [usbus3] 100045 D - 0xc6fa6acc [usbus3] 100044 D - 0xc6f9cb5c [usbus2] 100043 D - 0xc6f9cb2c [usbus2] 100042 D - 0xc6f9cafc [usbus2] 100041 D - 0xc6f9cacc [usbus2] 100039 D - 0xc6f96b5c [usbus1] 100038 D - 0xc6f96b2c [usbus1] 100037 D - 0xc6f96afc [usbus1] 100036 D - 0xc6f96acc [usbus1] 100034 D - 0xc6f91b5c [usbus0] 100033 D - 0xc6f91b2c [usbus0] 100032 D - 0xc6f91afc [usbus0] 100031 D - 0xc6f91acc [usbus0] 13 0 0 0 DL - 0xc0e06364 [yarrow] 4 0 0 0 DL - 0xc0e04104 [g_down] 3 0 0 0 DL - 0xc0e04100 [g_up] 2 0 0 0 DL - 0xc0e040f8 [g_event] 12 0 0 0 WL (threaded) [intr] 100065 I [irq12: psm0] 100064 I [irq1: atkbd0] 100062 I [swi0: uart] 100059 I [irq20: fwohci0] 100058 I [irq14: ata0] 100053 I [irq19: ehci0] 100040 I [irq18: ohci2 ohci4] 100035 I [irq17: ohci1 ohci3] 100030 I [irq16: hdac1 ohci0] 100029 I [irq22: atapci0] 100028 I [irq256: hdac0] 100027 I [irq9: acpi0] 100023 I [swi2: cambio] 100022 I [swi6: task queue] 100021 I [swi6: Giant taskq] 100019 I [swi5: +] 100012 I [swi3: vm] 100011 I [swi4: clock] 100010 I [swi4: clock] 100009 I [swi4: clock] 100008 I [swi4: clock] 100007 I [swi1: netisr 0] 11 0 0 0 RL (threaded) [idle] 100006 CanRun [idle: cpu0] 100005 Run CPU 1 [idle: cpu1] 100004 Run CPU 2 [idle: cpu2] 100003 Run CPU 3 [idle: cpu3] 1 0 1 0 SLs wait 0xc6d5dd48 [init] 10 0 0 0 DL audit_wo 0xc0e25020 [audit] 0 0 0 0 DLs (threaded) [kernel] 100066 D deadlkre 0xc0e06364 [deadlkres] 100060 D - 0xc6fda840 [fw0_taskq] 100026 D - 0xc6f2b0c0 [acpi_task_2] 100025 D - 0xc6f2b0c0 [acpi_task_1] 100024 D - 0xc6f2b0c0 [acpi_task_0] 100020 D - 0xc6f2b300 [thread taskq] 100018 D - 0xc6f2b580 [kqueue taskq] 100016 D - 0xc6d44e80 [firmware taskq] 100000 D sched 0xc0e041e0 [swapper] db:0:ps> allt Tracing command kldload pid 49890 tid 100096 td 0xc750f240 _end(c517a528,f611e868,f611e874,1,f611e878,...) at 0xc517dae0 vnode_pager_read(c78d27c4,f611e8f4,8,c4de1cf0,7,...) at vnode_pager_read+0x339 vn_read_chunk(c78d27c4,f611e8f4,c6d63380,c6d63380,8,...) at vn_read_chunk+0xec vn_rdwr(0,c78d27c4,c9c0a000,22fe0,0,...) at vn_rdwr+0x189 link_elf_load_file(c0d9f760,c92cda40,f611ec14,c750f240,0,...) at link_elf_load_file+0x4a3 linker_load_module(0,f611ec48,2,f611ec58,c088fb46,...) at linker_load_module+0x8f7 kern_kldload(c750f240,c70c6000,f611ec70,0,bfbfe950,...) at kern_kldload+0xec kldload(c750f240,f611ecf8,c,c750f240,f611ed2c,...) at kldload+0x74 syscall(f611ed38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (304, FreeBSD ELF32, kldload), eip = 0x280d75db, esp = 0xbfbfe94c, ebp = 0xbfbfee38 --- Tracing command sh pid 49887 tid 100164 td 0xc7ed2480 sched_switch(c7ed2480,0,104,f5c82ebd,3409,...) at sched_switch+0x279 mi_switch(104,0,0,c7a1f2a8,f6281b88,...) at mi_switch+0x12a sleepq_switch(c7ed2480,0,c0cbcce5,1a0,c7ed2480,...) at sleepq_switch+0xcc sleepq_catch_signals(0,100,f6281bd4,c08ac1dc,c7a1f2a8,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c7a1f2a8,5c,c0cd874a,100,0,...) at sleepq_wait_sig+0x18 _sleep(c7a1f2a8,c7a1f330,15c,c0cd874a,0,...) at _sleep+0x28c kern_wait(c7ed2480,ffffffff,f6281c74,2,0,...) at kern_wait+0xfa8 wait4(c7ed2480,f6281cf8,c,c7ed2480,f6281d2c,...) at wait4+0x3b syscall(f6281d38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (7, FreeBSD ELF32, wait4), eip = 0x2815f32b, esp = 0xbfbfd36c, ebp = 0xbfbfd388 --- Tracing command syslogd pid 49882 tid 100131 td 0xc73a7240 sched_switch(c73a7240,0,104,ee7dc88d,3409,...) at sched_switch+0x279 mi_switch(104,0,0,c7ec0d48,f6204a50,...) at mi_switch+0x12a sleepq_switch(c73a7240,0,c0cbcce5,1a0,c73a7240,...) at sleepq_switch+0xcc sleepq_catch_signals(0,c73a7240,f6204a90,c085c983,c9a6ada4,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c9a6ada4,0,c0cbd2cb,101,0,...) at sleepq_wait_sig+0x18 _cv_wait_sig(c9a6ada4,c9a6ad90,c0da0f60,c6ef8100,c9a61498,...) at _cv_wait_sig+0x193 seltdwait(c9a61498,58,c6d63380,c73a7240,0,...) at seltdwait+0xd7 kern_select(c73a7240,9,2842c0ac,0,0,0,20,bfbfe2b0,0) at kern_select+0x4de select(c73a7240,f6204cf8,c,c73a7240,f6204d2c,...) at select+0x66 syscall(f6204d38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (93, FreeBSD ELF32, select), eip = 0x28191763, esp = 0xbfbfe2ac, ebp = 0xbfbfee18 --- Tracing command devd pid 49700 tid 100168 td 0xc7ec3b40 sched_switch(c7ec3b40,0,104,8b4f4652,3409,...) at sched_switch+0x279 mi_switch(104,0,0,c81f7aa0,f628da50,...) at mi_switch+0x12a sleepq_switch(c7ec3b40,0,c0cbcce5,1a0,c7ec3b40,...) at sleepq_switch+0xcc sleepq_catch_signals(0,c7ec3b40,f628da90,c085c983,c6fd9ca4,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c6fd9ca4,0,c0cbd2cb,101,0,...) at sleepq_wait_sig+0x18 _cv_wait_sig(c6fd9ca4,c6fd9c90,58,c6d63380,c7ec3b40,...) at _cv_wait_sig+0x193 seltdwait(c73ae770,58,c6d63380,c7ec3b40,0,...) at seltdwait+0xd7 kern_select(c7ec3b40,6,bfbfe9a0,0,0,0,20,bfbfe970,10) at kern_select+0x4de select(c7ec3b40,f628dcf8,c,c7ec3b40,f628dd2c,...) at select+0x66 syscall(f628dd38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (93, FreeBSD ELF32, select), eip = 0x8088c03, esp = 0xbfbfe96c, ebp = 0xbfbfee48 --- Tracing command sh pid 49029 tid 100150 td 0xc7ed3900 sched_switch(c7ed3900,0,104,f528daed,3409,...) at sched_switch+0x279 mi_switch(104,0,0,c7ece000,f6251b88,...) at mi_switch+0x12a sleepq_switch(c7ed3900,0,c0cbcce5,1a0,c7ed3900,...) at sleepq_switch+0xcc sleepq_catch_signals(0,100,f6251bd4,c08ac1dc,c7ece000,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c7ece000,5c,c0cd874a,100,0,...) at sleepq_wait_sig+0x18 _sleep(c7ece000,c7ece088,15c,c0cd874a,0,...) at _sleep+0x28c kern_wait(c7ed3900,ffffffff,f6251c74,2,0,...) at kern_wait+0xfa8 wait4(c7ed3900,f6251cf8,c,c7ed3900,f6251d2c,...) at wait4+0x3b syscall(f6251d38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (7, FreeBSD ELF32, wait4), eip = 0x2815f32b, esp = 0xbfbfe98c, ebp = 0xbfbfe9a8 --- Tracing command flowcleaner pid 21 tid 100076 td 0xc70d9240 sched_switch(c70d9240,0,104,e42d630d,3407,...) at sched_switch+0x279 mi_switch(104,0,c70d9240,c70d9240,f3ee2ca0,...) at mi_switch+0x12a sleepq_switch(c70d9240,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e19fa8,0,c0cc1f35,1,0,...) at sleepq_timedwait+0x3e _cv_timedwait(c0e19fa8,c0e19fb0,2710,3cf,f3ee2cf4,...) at _cv_timedwait+0x1a4 flowtable_cleaner(0,f3ee2d38,0,0,0,...) at flowtable_cleaner+0x1fe fork_exit(c094ce20,0,f3ee2d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ee2d70, ebp = 0 --- Tracing command softdepflush pid 20 tid 100075 td 0xc70d9480 sched_switch(c70d9480,0,104,a59d3d52,3409,...) at sched_switch+0x279 mi_switch(104,0,c70d9480,0,f3edfc8c,...) at mi_switch+0x12a sleepq_switch(c70d9480,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e25700,44,c0cd4b1c,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e25700,c0e256a4,44,c0cd4b1c,3e8,...) at _sleep+0x272 softdep_flush(0,f3edfd38,0,0,0,...) at softdep_flush+0x30c fork_exit(c0ae1ca0,0,f3edfd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3edfd70, ebp = 0 --- Tracing command vnlru pid 19 tid 100074 td 0xc70d96c0 sched_switch(c70d96c0,0,104,9dac0c3b,3409,...) at sched_switch+0x279 mi_switch(104,0,c70d96c0,0,f3edcc5c,...) at mi_switch+0x12a sleepq_switch(c70d96c0,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c733c550,50,c0cc18de,0,0,...) at sleepq_timedwait+0x3e _sleep(c733c550,c0e19d74,250,c0cc18de,3e8,...) at _sleep+0x272 vnlru_proc(0,f3edcd38,0,0,0,...) at vnlru_proc+0x106 fork_exit(c09374d0,0,f3edcd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3edcd70, ebp = 0 --- Tracing command syncer pid 18 tid 100073 td 0xc70d9900 sched_switch(c70d9900,0,104,ef138d16,3409,...) at sched_switch+0x279 mi_switch(104,0,c70d9900,c70d9900,f3ed9c64,...) at mi_switch+0x12a sleepq_switch(c70d9900,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e19db4,0,c0cc10bc,1,0,...) at sleepq_timedwait+0x3e _cv_timedwait(c0e19db4,c0e19da0,3e8,c733c7f8,4e20,...) at _cv_timedwait+0x1a4 sched_sync(0,f3ed9d38,0,0,0,...) at sched_sync+0x527 fork_exit(c0936690,0,f3ed9d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ed9d70, ebp = 0 --- Tracing command bufdaemon pid 17 tid 100072 td 0xc70d9b40 sched_switch(c70d9b40,0,104,f0459179,3409,...) at sched_switch+0x279 mi_switch(104,0,c70d9b40,0,f3ed6c9c,...) at mi_switch+0x12a sleepq_switch(c70d9b40,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e19ae8,44,c0cbfaf0,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e19ae8,c0e19aec,44,c0cbfaf0,3e8,...) at _sleep+0x272 buf_daemon(0,f3ed6d38,0,0,0,...) at buf_daemon+0x18f fork_exit(c091c2e0,0,f3ed6d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ed6d70, ebp = 0 --- Tracing command pagezero pid 16 tid 100071 td 0xc70d9d80 sched_switch(c70d9d80,0,104,ab3a6b6b,33a9,...) at sched_switch+0x279 mi_switch(104,0,c70d9d80,0,f3ed3c9c,...) at mi_switch+0x12a sleepq_switch(c70d9d80,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e2655c,0,c0cd8abc,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e2655c,c0e26000,0,c0cd8abc,493e0,...) at _sleep+0x272 vm_pagezero(0,f3ed3d38,0,0,0,...) at vm_pagezero+0xd2 fork_exit(c0b279a0,0,f3ed3d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ed3d70, ebp = 0 --- Tracing command vmdaemon pid 15 tid 100070 td 0xc70db000 sched_switch(c70db000,0,104,971e131a,15,...) at sched_switch+0x279 mi_switch(104,0,c70db000,0,f3ed0c5c,...) at mi_switch+0x12a sleepq_switch(c70db000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0e26144,68,c0cbfaf0,0,0,...) at sleepq_wait+0x39 _sleep(c0e26144,c0e26148,68,c0cbfaf0,0,...) at _sleep+0x2a2 vm_daemon(0,f3ed0d38,0,0,0,...) at vm_daemon+0x78 fork_exit(c0b21630,0,f3ed0d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ed0d70, ebp = 0 --- Tracing command writed pid 9 tid 100069 td 0xc70db240 sched_switch(c70db240,0,104,971dfc87,15,...) at sched_switch+0x279 mi_switch(104,0,c70db240,c70db240,f3ecdca4,...) at mi_switch+0x12a sleepq_switch(c70db240,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0e26524,0,c0cd859b,1,0,...) at sleepq_wait+0x39 _cv_wait(c0e26524,c0e26080,0,c70db240,f3ecdcf4,...) at _cv_wait+0x189 vnode_writedirty_daemon(0,f3ecdd38,0,0,0,...) at vnode_writedirty_daemon+0x89 fork_exit(c0b24940,0,f3ecdd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ecdd70, ebp = 0 --- Tracing command pagedaemon pid 8 tid 100068 td 0xc70db480 sched_switch(c70db480,0,104,2507336,3408,...) at sched_switch+0x279 mi_switch(104,0,c70db480,0,f3ecabf0,...) at mi_switch+0x12a sleepq_switch(c70db480,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e2610c,44,c0cbfaf0,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e2610c,c0e26000,44,c0cbfaf0,1388,...) at _sleep+0x272 vm_pageout(0,f3ecad38,0,0,0,...) at vm_pageout+0x2e6 fork_exit(c0b200c0,0,f3ecad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3ecad70, ebp = 0 --- Tracing command xpt_thrd pid 7 tid 100067 td 0xc70db6c0 sched_switch(c70db6c0,0,104,e5ddb999,13,...) at sched_switch+0x279 mi_switch(104,0,c70db6c0,0,f3e67c94,...) at mi_switch+0x12a sleepq_switch(c70db6c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0dd24d4,4c,c0c5a6a4,0,0,...) at sleepq_wait+0x39 _sleep(c0dd24d4,c0dd2518,4c,c0c5a6a4,0,...) at _sleep+0x2a2 xpt_scanner_thread(0,f3e67d38,0,0,0,...) at xpt_scanner_thread+0x47 fork_exit(c0486850,0,f3e67d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e67d70, ebp = 0 --- Tracing command fdc0 pid 6 tid 100063 td 0xc6f9b240 sched_switch(c6f9b240,0,104,fbefa176,3409,...) at sched_switch+0x279 mi_switch(104,0,c6f9b240,0,f3e5bbec,...) at mi_switch+0x12a sleepq_switch(c6f9b240,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c70cfc3c,4c,c0cb24d6,0,0,...) at sleepq_timedwait+0x3e _sleep(c70cfc3c,c70cfcf0,4c,c0cb24d6,3e8,...) at _sleep+0x272 fdc_thread(c70cfc00,f3e5bd38,0,0,0,...) at fdc_thread+0x36d fork_exit(c0ba5b20,c70cfc00,f3e5bd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e5bd70, ebp = 0 --- Tracing command fw0_probe pid 5 tid 100061 td 0xc6f9b6c0 sched_switch(c6f9b6c0,0,104,e5f6ca2c,13,...) at sched_switch+0x279 mi_switch(104,0,0,c6f2d000,f3e4b7ac,...) at mi_switch+0x12a sleepq_switch(c6f9b6c0,0,c0cbcce5,1a0,c6f9b6c0,...) at sleepq_switch+0xcc sleepq_catch_signals(0,100,f3e4b7f8,c08ac1dc,c6fdb000,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c6fdb000,5c,c0cb24d6,100,0,...) at sleepq_wait_sig+0x18 _sleep(c6fdb000,c6fdf488,15c,c0cb24d6,0,...) at _sleep+0x28c fw_bus_probe_thread(c6fdb000,f3e4bd38,0,0,0,...) at fw_bus_probe_thread+0xb35 fork_exit(c06637d0,c6fdb000,f3e4bd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e4bd70, ebp = 0 --- Tracing command usb pid 14 tid 100057 td 0xc6faf000 sched_switch(c6faf000,0,104,7c4d7602,13,...) at sched_switch+0x279 mi_switch(104,0,c6faf000,c6faf000,f3e34c9c,...) at mi_switch+0x12a sleepq_switch(c6faf000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fb4d0c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fb4d0c,c6fb4dac,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fb4d04,f3e34d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fb4d04,f3e34d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e34d70, ebp = 0 --- Tracing command usb pid 14 tid 100056 td 0xc6faf240 sched_switch(c6faf240,0,104,f0c1b19d,3408,...) at sched_switch+0x279 mi_switch(104,0,c6faf240,c6faf240,f3e31c9c,...) at mi_switch+0x12a sleepq_switch(c6faf240,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fb4cdc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fb4cdc,c6fb4dac,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fb4cd4,f3e31d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fb4cd4,f3e31d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e31d70, ebp = 0 --- Tracing command usb pid 14 tid 100055 td 0xc6faf480 sched_switch(c6faf480,0,104,7be82b9e,13,...) at sched_switch+0x279 mi_switch(104,0,c6faf480,c6faf480,f3e2ec9c,...) at mi_switch+0x12a sleepq_switch(c6faf480,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fb4cac,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fb4cac,c6fb4dac,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fb4ca4,f3e2ed38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fb4ca4,f3e2ed38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e2ed70, ebp = 0 --- Tracing command usb pid 14 tid 100054 td 0xc6faf6c0 sched_switch(c6faf6c0,0,104,7be82020,13,...) at sched_switch+0x279 mi_switch(104,0,c6faf6c0,c6faf6c0,f3e2bc9c,...) at mi_switch+0x12a sleepq_switch(c6faf6c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fb4c7c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fb4c7c,c6fb4dac,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fb4c74,f3e2bd38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fb4c74,f3e2bd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e2bd70, ebp = 0 --- Tracing command usb pid 14 tid 100052 td 0xc6fafb40 sched_switch(c6fafb40,0,104,7be81675,13,...) at sched_switch+0x279 mi_switch(104,0,c6fafb40,c6fafb40,f3e23c9c,...) at mi_switch+0x12a sleepq_switch(c6fafb40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6faab5c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6faab5c,c6faabfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6faab54,f3e23d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6faab54,f3e23d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e23d70, ebp = 0 --- Tracing command usb pid 14 tid 100051 td 0xc6fafd80 sched_switch(c6fafd80,0,104,e82b84c1,3408,...) at sched_switch+0x279 mi_switch(104,0,c6fafd80,c6fafd80,f3e20c9c,...) at mi_switch+0x12a sleepq_switch(c6fafd80,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6faab2c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6faab2c,c6faabfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6faab24,f3e20d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6faab24,f3e20d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e20d70, ebp = 0 --- Tracing command usb pid 14 tid 100050 td 0xc6f796c0 sched_switch(c6f796c0,0,104,7b850a49,13,...) at sched_switch+0x279 mi_switch(104,0,c6f796c0,c6f796c0,f3e1dc9c,...) at mi_switch+0x12a sleepq_switch(c6f796c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6faaafc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6faaafc,c6faabfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6faaaf4,f3e1dd38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6faaaf4,f3e1dd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e1dd70, ebp = 0 --- Tracing command usb pid 14 tid 100049 td 0xc6f79900 sched_switch(c6f79900,0,104,7b850039,13,...) at sched_switch+0x279 mi_switch(104,0,c6f79900,c6f79900,f3e1ac9c,...) at mi_switch+0x12a sleepq_switch(c6f79900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6faaacc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6faaacc,c6faabfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6faaac4,f3e1ad38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6faaac4,f3e1ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e1ad70, ebp = 0 --- Tracing command usb pid 14 tid 100048 td 0xc6f79b40 sched_switch(c6f79b40,0,104,7b84f59d,13,...) at sched_switch+0x279 mi_switch(104,0,c6f79b40,c6f79b40,f3e16c9c,...) at mi_switch+0x12a sleepq_switch(c6f79b40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fa6b5c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fa6b5c,c6fa6bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fa6b54,f3e16d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fa6b54,f3e16d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e16d70, ebp = 0 --- Tracing command usb pid 14 tid 100047 td 0xc6f79d80 sched_switch(c6f79d80,0,104,e7a22955,3408,...) at sched_switch+0x279 mi_switch(104,0,c6f79d80,c6f79d80,f3e13c9c,...) at mi_switch+0x12a sleepq_switch(c6f79d80,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fa6b2c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fa6b2c,c6fa6bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fa6b24,f3e13d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fa6b24,f3e13d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e13d70, ebp = 0 --- Tracing command usb pid 14 tid 100046 td 0xc6f9a000 sched_switch(c6f9a000,0,104,7b21ecd9,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9a000,c6f9a000,f3e10c9c,...) at mi_switch+0x12a sleepq_switch(c6f9a000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fa6afc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fa6afc,c6fa6bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fa6af4,f3e10d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fa6af4,f3e10d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e10d70, ebp = 0 --- Tracing command usb pid 14 tid 100045 td 0xc6f9a240 sched_switch(c6f9a240,0,104,7b21ddfd,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9a240,c6f9a240,f3e0dc9c,...) at mi_switch+0x12a sleepq_switch(c6f9a240,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fa6acc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6fa6acc,c6fa6bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6fa6ac4,f3e0dd38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6fa6ac4,f3e0dd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e0dd70, ebp = 0 --- Tracing command usb pid 14 tid 100044 td 0xc6f9a480 sched_switch(c6f9a480,0,104,7b21d1c3,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9a480,c6f9a480,f3e09c9c,...) at mi_switch+0x12a sleepq_switch(c6f9a480,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f9cb5c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f9cb5c,c6f9cbfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f9cb54,f3e09d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f9cb54,f3e09d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e09d70, ebp = 0 --- Tracing command usb pid 14 tid 100043 td 0xc6f9a6c0 sched_switch(c6f9a6c0,0,104,e718caf1,3408,...) at sched_switch+0x279 mi_switch(104,0,c6f9a6c0,c6f9a6c0,f3e06c9c,...) at mi_switch+0x12a sleepq_switch(c6f9a6c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f9cb2c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f9cb2c,c6f9cbfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f9cb24,f3e06d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f9cb24,f3e06d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e06d70, ebp = 0 --- Tracing command usb pid 14 tid 100042 td 0xc6f9a900 sched_switch(c6f9a900,0,104,7abf2d2f,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9a900,c6f9a900,f3e03c9c,...) at mi_switch+0x12a sleepq_switch(c6f9a900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f9cafc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f9cafc,c6f9cbfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f9caf4,f3e03d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f9caf4,f3e03d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e03d70, ebp = 0 --- Tracing command usb pid 14 tid 100041 td 0xc6f9ab40 sched_switch(c6f9ab40,0,104,7abf22d5,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9ab40,c6f9ab40,f3e00c9c,...) at mi_switch+0x12a sleepq_switch(c6f9ab40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f9cacc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f9cacc,c6f9cbfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f9cac4,f3e00d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f9cac4,f3e00d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e00d70, ebp = 0 --- Tracing command usb pid 14 tid 100039 td 0xc6f9b000 sched_switch(c6f9b000,0,104,7abf173e,13,...) at sched_switch+0x279 mi_switch(104,0,c6f9b000,c6f9b000,f3df9c9c,...) at mi_switch+0x12a sleepq_switch(c6f9b000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f96b5c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f96b5c,c6f96bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f96b54,f3df9d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f96b54,f3df9d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3df9d70, ebp = 0 --- Tracing command usb pid 14 tid 100038 td 0xc6f37d80 sched_switch(c6f37d80,0,104,e6aaeca7,3408,...) at sched_switch+0x279 mi_switch(104,0,c6f37d80,c6f37d80,f3df6c9c,...) at mi_switch+0x12a sleepq_switch(c6f37d80,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f96b2c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f96b2c,c6f96bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f96b24,f3df6d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f96b24,f3df6d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3df6d70, ebp = 0 --- Tracing command usb pid 14 tid 100037 td 0xc6f77000 sched_switch(c6f77000,0,104,7a5c1e06,13,...) at sched_switch+0x279 mi_switch(104,0,c6f77000,c6f77000,f3df3c9c,...) at mi_switch+0x12a sleepq_switch(c6f77000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f96afc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f96afc,c6f96bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f96af4,f3df3d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f96af4,f3df3d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3df3d70, ebp = 0 --- Tracing command usb pid 14 tid 100036 td 0xc6f77240 sched_switch(c6f77240,0,104,7a5c12e3,13,...) at sched_switch+0x279 mi_switch(104,0,c6f77240,c6f77240,f3df0c9c,...) at mi_switch+0x12a sleepq_switch(c6f77240,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f96acc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f96acc,c6f96bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f96ac4,f3df0d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f96ac4,f3df0d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3df0d70, ebp = 0 --- Tracing command usb pid 14 tid 100034 td 0xc6f776c0 sched_switch(c6f776c0,0,104,7a5c0623,13,...) at sched_switch+0x279 mi_switch(104,0,c6f776c0,c6f776c0,f3de9c9c,...) at mi_switch+0x12a sleepq_switch(c6f776c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f91b5c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f91b5c,c6f91bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f91b54,f3de9d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f91b54,f3de9d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3de9d70, ebp = 0 --- Tracing command usb pid 14 tid 100033 td 0xc6f77900 sched_switch(c6f77900,0,104,e63d3b2d,3408,...) at sched_switch+0x279 mi_switch(104,0,c6f77900,c6f77900,f3de6c9c,...) at mi_switch+0x12a sleepq_switch(c6f77900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f91b2c,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f91b2c,c6f91bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f91b24,f3de6d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f91b24,f3de6d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3de6d70, ebp = 0 --- Tracing command usb pid 14 tid 100032 td 0xc6f77b40 sched_switch(c6f77b40,0,104,79f91c85,13,...) at sched_switch+0x279 mi_switch(104,0,c6f77b40,c6f77b40,f3de3c9c,...) at mi_switch+0x12a sleepq_switch(c6f77b40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f91afc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f91afc,c6f91bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f91af4,f3de3d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f91af4,f3de3d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3de3d70, ebp = 0 --- Tracing command usb pid 14 tid 100031 td 0xc6f77d80 sched_switch(c6f77d80,0,104,79f910f6,13,...) at sched_switch+0x279 mi_switch(104,0,c6f77d80,c6f77d80,f3de0c9c,...) at mi_switch+0x12a sleepq_switch(c6f77d80,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f91acc,0,c0cb24d6,1,0,...) at sleepq_wait+0x39 _cv_wait(c6f91acc,c6f91bfc,c0cabfbe,68,0,...) at _cv_wait+0x189 usb_process(c6f91ac4,f3de0d38,0,0,0,...) at usb_process+0x176 fork_exit(c07cfcb0,c6f91ac4,f3de0d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3de0d70, ebp = 0 --- Tracing command yarrow pid 13 tid 100017 td 0xc6d61240 sched_switch(c6d61240,0,104,fbca8565,3409,...) at sched_switch+0x279 mi_switch(104,0,c6d61240,2,c6b55c6c,...) at mi_switch+0x12a sleepq_switch(c6d61240,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e06364,0,c0cb24d6,2,0,...) at sleepq_timedwait+0x3e _sleep(c0e06364,0,0,c0cb24d6,64,...) at _sleep+0x272 pause(c0cb24d6,64,0,0,0,...) at pause+0x30 random_kthread(0,c6b55d38,0,0,0,...) at random_kthread+0x219 fork_exit(c07426a0,0,c6b55d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b55d70, ebp = 0 --- Tracing command g_down pid 4 tid 100015 td 0xc6d616c0 sched_switch(c6d616c0,0,104,f86bb0d5,3409,...) at sched_switch+0x279 mi_switch(104,0,c6d616c0,0,c6b4fc58,...) at mi_switch+0x12a sleepq_switch(c6d616c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0e04104,4c,c0cb24d6,0,0,...) at sleepq_wait+0x39 _sleep(c0e04104,c0e04068,24c,c0cb24d6,0,...) at _sleep+0x2a2 g_io_schedule_down(c6d616c0,4c,c0cb3133,72,0,...) at g_io_schedule_down+0x56 g_down_procbody(0,c6b4fd38,0,0,0,...) at g_down_procbody+0x68 fork_exit(c083e3d0,0,c6b4fd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b4fd70, ebp = 0 --- Tracing command g_up pid 3 tid 100014 td 0xc6d61900 sched_switch(c6d61900,0,104,f8a70441,3409,...) at sched_switch+0x279 mi_switch(104,0,c6d61900,0,c6b4cc7c,...) at mi_switch+0x12a sleepq_switch(c6d61900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0e04100,4c,c0cb24d6,0,0,...) at sleepq_wait+0x39 _sleep(c0e04100,c0e04088,24c,c0cb24d6,0,...) at _sleep+0x2a2 g_io_schedule_up(c6d61900,4c,c0cb3133,5b,0,...) at g_io_schedule_up+0xbd g_up_procbody(0,c6b4cd38,0,0,0,...) at g_up_procbody+0x68 fork_exit(c083e440,0,c6b4cd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b4cd70, ebp = 0 --- Tracing command g_event pid 2 tid 100013 td 0xc6d61b40 sched_switch(c6d61b40,0,104,faed58d7,3409,...) at sched_switch+0x279 mi_switch(104,0,c6d61b40,0,c6b49c98,...) at mi_switch+0x12a sleepq_switch(c6d61b40,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e040f8,4c,c0cb24d6,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e040f8,0,4c,c0cb24d6,64,...) at _sleep+0x272 g_event_procbody(0,c6b49d38,0,0,0,...) at g_event_procbody+0xa6 fork_exit(c083e4b0,0,c6b49d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b49d70, ebp = 0 --- Tracing command intr pid 12 tid 100065 td 0xc70dbb40 fork_trampoline() at fork_trampoline Tracing command intr pid 12 tid 100064 td 0xc70dbd80 sched_switch(c70dbd80,0,109,79f76bd8,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d632f0,...) at mi_switch+0x12a ithread_loop(c70c7ba0,f3e5ed38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c70c7ba0,f3e5ed38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e5ed70, ebp = 0 --- Tracing command intr pid 12 tid 100062 td 0xc6f9b480 sched_switch(c6f9b480,0,109,f5b2ea49,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6fe49f0,...) at mi_switch+0x12a ithread_loop(c70c79f0,f3e4ed38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c70c79f0,f3e4ed38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e4ed70, ebp = 0 --- Tracing command intr pid 12 tid 100059 td 0xc6f9bb40 sched_switch(c6f9bb40,0,109,79f1759d,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62870,...) at mi_switch+0x12a ithread_loop(c6fb6640,f3e42d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6fb6640,f3e42d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e42d70, ebp = 0 --- Tracing command intr pid 12 tid 100058 td 0xc6f9bd80 sched_switch(c6f9bd80,0,109,e85b4a7e,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62b70,...) at mi_switch+0x12a ithread_loop(c6f8dbc0,f3e3ad38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f8dbc0,f3e3ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e3ad70, ebp = 0 --- Tracing command intr pid 12 tid 100053 td 0xc6faf900 fork_trampoline() at fork_trampoline Tracing command intr pid 12 tid 100040 td 0xc6f9ad80 sched_switch(c6f9ad80,0,109,9da8ab04,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62970,...) at mi_switch+0x12a ithread_loop(c6f8d600,f3dfdd38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f8d600,f3dfdd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3dfdd70, ebp = 0 --- Tracing command intr pid 12 tid 100035 td 0xc6f77480 sched_switch(c6f77480,0,109,9ce8b8de,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d629f0,...) at mi_switch+0x12a ithread_loop(c6f88980,f3dedd38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f88980,f3dedd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3dedd70, ebp = 0 --- Tracing command intr pid 12 tid 100030 td 0xc6f79000 sched_switch(c6f79000,0,109,f42ecba5,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62a70,...) at mi_switch+0x12a ithread_loop(c6f887c0,f3dddd38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f887c0,f3dddd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3dddd70, ebp = 0 --- Tracing command intr pid 12 tid 100029 td 0xc6f79240 sched_switch(c6f79240,0,109,f8a65d27,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62770,...) at mi_switch+0x12a ithread_loop(c6f88040,f3cced38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f88040,f3cced38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3cced70, ebp = 0 --- Tracing command intr pid 12 tid 100028 td 0xc6f79480 sched_switch(c6f79480,0,109,ed0fdcab,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6f639f0,...) at mi_switch+0x12a ithread_loop(c6f739b0,c6ba4d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6f739b0,c6ba4d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6ba4d70, ebp = 0 --- Tracing command intr pid 12 tid 100027 td 0xc6da56c0 sched_switch(c6da56c0,0,109,79f80517,13,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62df0,...) at mi_switch+0x12a ithread_loop(c6d5c610,c6b9ad38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c610,c6b9ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b9ad70, ebp = 0 --- Tracing command intr pid 12 tid 100023 td 0xc6f37000 sched_switch(c6f37000,0,109,95ba2869,15,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d63870,...) at mi_switch+0x12a ithread_loop(c6d5c3c0,c6b67d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c3c0,c6b67d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b67d70, ebp = 0 --- Tracing command intr pid 12 tid 100022 td 0xc6f37240 sched_switch(c6f37240,0,109,587082eb,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d63a70,...) at mi_switch+0x12a ithread_loop(c6d27a10,c6b64d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d27a10,c6b64d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b64d70, ebp = 0 --- Tracing command intr pid 12 tid 100021 td 0xc6f37480 fork_trampoline() at fork_trampoline Tracing command intr pid 12 tid 100019 td 0xc6f37900 fork_trampoline() at fork_trampoline Tracing command intr pid 12 tid 100012 td 0xc6d61d80 fork_trampoline() at fork_trampoline Tracing command intr pid 12 tid 100011 td 0xc6da5000 sched_switch(c6da5000,0,109,f0457a99,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d620f0,...) at mi_switch+0x12a ithread_loop(c6d5c1d0,c6b43d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c1d0,c6b43d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b43d70, ebp = 0 --- Tracing command intr pid 12 tid 100010 td 0xc6da5240 sched_switch(c6da5240,0,109,5c1c6e09,3408,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62170,...) at mi_switch+0x12a ithread_loop(c6d5c1e0,c6b40d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c1e0,c6b40d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b40d70, ebp = 0 --- Tracing command intr pid 12 tid 100009 td 0xc6da5480 sched_switch(c6da5480,0,109,fbca25ae,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62570,...) at mi_switch+0x12a ithread_loop(c6d5c1f0,c6b3dd38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c1f0,c6b3dd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b3dd70, ebp = 0 --- Tracing command intr pid 12 tid 100008 td 0xc6d5f000 sched_switch(c6d5f000,0,109,fd28bf58,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d625f0,...) at mi_switch+0x12a ithread_loop(c6d5c200,c6b3ad38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c200,c6b3ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b3ad70, ebp = 0 --- Tracing command intr pid 12 tid 100007 td 0xc6d5f240 sched_switch(c6d5f240,0,109,9558c832,3409,...) at sched_switch+0x279 mi_switch(109,0,c0cb68c8,52d,c6d62670,...) at mi_switch+0x12a ithread_loop(c6d5c210,c6b37d38,0,0,0,...) at ithread_loop+0x160 fork_exit(c087aeb0,c6d5c210,c6b37d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b37d70, ebp = 0 --- Tracing command idle pid 11 tid 100006 td 0xc6d5f480 sched_switch(c6d5f480,0,60c,f8a70405,3409,...) at sched_switch+0x279 mi_switch(60c,0,c0cbacaa,804,0,...) at mi_switch+0x12a sched_preempt(c6d5f480,0,c6d61900,c6b33cb0,c0bcd2de,...) at sched_preempt+0x7c ipi_bitmap_handler(8,28,28,12,c0e09f00,...) at ipi_bitmap_handler+0x34 Xipi_intr_bitmap_handler() at Xipi_intr_bitmap_handler+0x2e --- interrupt, eip = 0xc0893607, esp = 0xc6b33c9c, ebp = 0xc6b33cb0 --- _thread_lock_flags(c6d5f480,0,c0cbacaa,9f8,c6d5f480,...) at _thread_lock_flags+0xa7 sched_idletd(0,c6b33d38,0,0,0,...) at sched_idletd+0x274 fork_exit(c08c67a0,0,c6b33d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b33d70, ebp = 0 --- Tracing command idle pid 11 tid 100005 td 0xc6d5f6c0 cpustop_handler(2,c6b30c1c,c0beae26,c6fc6700,8e,...) at cpustop_handler+0x32 ipi_nmi_handler(c6fc6700,8e,c6d63100,c6b30bc8,c6d5daa0,...) at ipi_nmi_handler+0x2f trap(c6b30c28) at trap+0x36 calltrap() at calltrap+0x6 --- trap 0x13, eip = 0xc0bc10d5, esp = 0xc6b30c68, ebp = 0xc6b30c68 --- acpi_cpu_c1(c6b30cf4,c6b30cd0,1,ffffffff,c6b30cb0,...) at acpi_cpu_c1+0x5 acpi_cpu_idle(c0e0a580,0,c6b30cb0,c0bd8a5b,1,...) at acpi_cpu_idle+0x107 cpu_idle_amdc1e(1,c6b30cf4,c08c69e3,1,c6b30cd0,...) at cpu_idle_amdc1e+0x56 cpu_idle(1,c6b30cd0,c0cbacaa,9f8,c6d5f6c0,...) at cpu_idle+0x1b sched_idletd(0,c6b30d38,0,0,0,...) at sched_idletd+0x243 fork_exit(c08c67a0,0,c6b30d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b30d70, ebp = 0 --- Tracing command idle pid 11 tid 100004 td 0xc6d5f900 cpustop_handler(4,c6b2dc1c,c0beae26,c6d5f900,c6f9b240,...) at cpustop_handler+0x32 ipi_nmi_handler(c6d5f900,c6f9b240,c6d5f900,c6b2dba8,c6d5daa0,...) at ipi_nmi_handler+0x2f trap(c6b2dc28) at trap+0x36 calltrap() at calltrap+0x6 --- trap 0x13, eip = 0xc0bc10d5, esp = 0xc6b2dc68, ebp = 0xc6b2dc68 --- acpi_cpu_c1(c6b2dcf4,c6b2dcd0,2,ffffffff,c6b2dcb0,...) at acpi_cpu_c1+0x5 acpi_cpu_idle(c0e0ac00,0,c6b2dcb0,c0bd8a5b,0,...) at acpi_cpu_idle+0x107 cpu_idle_amdc1e(0,c6b2dcf4,c08c69e3,0,c6b2dcd0,...) at cpu_idle_amdc1e+0x56 cpu_idle(0,c6b2dcd0,c0cbacaa,9f8,c6d5f900,...) at cpu_idle+0x1b sched_idletd(0,c6b2dd38,0,0,0,...) at sched_idletd+0x243 fork_exit(c08c67a0,0,c6b2dd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b2dd70, ebp = 0 --- Tracing command idle pid 11 tid 100003 td 0xc6d5fb40 cpustop_handler(8,c6b2ac1c,c0beae26,c6b2abb4,c0bf4695,...) at cpustop_handler+0x32 ipi_nmi_handler(c6b2abb4,c0bf4695,c6d5fb40,c6b2aba8,c6d5daa0,...) at ipi_nmi_handler+0x2f trap(c6b2ac28) at trap+0x36 calltrap() at calltrap+0x6 --- trap 0x13, eip = 0xc0bc10d5, esp = 0xc6b2ac68, ebp = 0xc6b2ac68 --- acpi_cpu_c1(30,c6b2acd0,3,ffffffff,c6b2acb0,...) at acpi_cpu_c1+0x5 acpi_cpu_idle(c0e0b280,0,c6b2acb0,c0bd8a5b,0,...) at acpi_cpu_idle+0x107 cpu_idle_amdc1e(0,c6b2acf4,c08c69e3,0,c6b2acd0,...) at cpu_idle_amdc1e+0x56 cpu_idle(0,c6b2acd0,c0cbacaa,9f8,c6d5fb40,...) at cpu_idle+0x1b sched_idletd(0,c6b2ad38,0,0,0,...) at sched_idletd+0x243 fork_exit(c08c67a0,0,c6b2ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b2ad70, ebp = 0 --- Tracing command init pid 1 tid 100002 td 0xc6d5fd80 sched_switch(c6d5fd80,0,104,ee7ff9d5,3409,...) at sched_switch+0x279 mi_switch(104,0,0,c6d5dd48,c6b26b88,...) at mi_switch+0x12a sleepq_switch(c6d5fd80,0,c0cbcce5,1a0,c6d5fd80,...) at sleepq_switch+0xcc sleepq_catch_signals(0,100,c6b26bd4,c08ac1dc,c6d5dd48,...) at sleepq_catch_signals+0x5b sleepq_wait_sig(c6d5dd48,5c,c0cd874a,100,0,...) at sleepq_wait_sig+0x18 _sleep(c6d5dd48,c6d5ddd0,15c,c0cd874a,0,...) at _sleep+0x28c kern_wait(c6d5fd80,ffffffff,c6b26c74,2,0,...) at kern_wait+0xfa8 wait4(c6d5fd80,c6b26cf8,c,c6d5fd80,c6b26d2c,...) at wait4+0x3b syscall(c6b26d38) at syscall+0x2d3 Xint0x80_syscall() at Xint0x80_syscall+0x20 --- syscall (7, FreeBSD ELF32, wait4), eip = 0x805523f, esp = 0xbfbfe79c, ebp = 0xbfbfe7b8 --- Tracing command audit pid 10 tid 100001 td 0xc6d61000 sched_switch(c6d61000,0,104,79f84d02,13,...) at sched_switch+0x279 mi_switch(104,0,c6d61000,c6d61000,c6b23c7c,...) at mi_switch+0x12a sleepq_switch(c6d61000,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c0e25020,0,c0cd2c5c,1,0,...) at sleepq_wait+0x39 _cv_wait(c0e25020,c0e25004,0,0,0,...) at _cv_wait+0x189 audit_worker(0,c6b23d38,0,0,0,...) at audit_worker+0x6f fork_exit(c0ab5870,0,c6b23d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b23d70, ebp = 0 --- Tracing command kernel pid 0 tid 100066 td 0xc70db900 sched_switch(c70db900,0,104,3b461f5f,3409,...) at sched_switch+0x279 mi_switch(104,0,c70db900,2,f3e64c68,...) at mi_switch+0x12a sleepq_switch(c70db900,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e06364,0,c0cb5680,2,0,...) at sleepq_timedwait+0x3e _sleep(c0e06364,0,0,c0cb5680,bb8,...) at _sleep+0x272 pause(c0cb5680,bb8,c0cb561f,c7,0,...) at pause+0x30 deadlkres(0,f3e64d38,0,0,0,...) at deadlkres+0x3af fork_exit(c085be40,0,f3e64d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e64d70, ebp = 0 --- Tracing command kernel pid 0 tid 100060 td 0xc6f9b900 sched_switch(c6f9b900,0,104,f29e2cfc,3409,...) at sched_switch+0x279 mi_switch(104,0,c6f9b900,c6fda858,f3e48ca4,...) at mi_switch+0x12a sleepq_switch(c6f9b900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6fda840,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 msleep_spin(c6fda840,c6fda858,c0cb24d6,0,f3e48cf4,...) at msleep_spin+0x185 taskqueue_thread_loop(c6fdf49c,f3e48d38,0,0,0,...) at taskqueue_thread_loop+0xe5 fork_exit(c08e0150,c6fdf49c,f3e48d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xf3e48d70, ebp = 0 --- Tracing command kernel pid 0 tid 100026 td 0xc6da5900 sched_switch(c6da5900,0,104,e5faa8d9,13,...) at sched_switch+0x279 mi_switch(104,0,c6da5900,c6f2b0d8,c6b70ca4,...) at mi_switch+0x12a sleepq_switch(c6da5900,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f2b0c0,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 msleep_spin(c6f2b0c0,c6f2b0d8,c0cb24d6,0,c6b70cf4,...) at msleep_spin+0x185 taskqueue_thread_loop(c0dd5340,c6b70d38,0,0,0,...) at taskqueue_thread_loop+0xe5 fork_exit(c08e0150,c0dd5340,c6b70d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b70d70, ebp = 0 --- Tracing command kernel pid 0 tid 100025 td 0xc6da5b40 sched_switch(c6da5b40,0,104,e5faa00d,13,...) at sched_switch+0x279 mi_switch(104,0,c6da5b40,c6f2b0d8,c6b6dca4,...) at mi_switch+0x12a sleepq_switch(c6da5b40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f2b0c0,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 msleep_spin(c6f2b0c0,c6f2b0d8,c0cb24d6,0,c6b6dcf4,...) at msleep_spin+0x185 taskqueue_thread_loop(c0dd5340,c6b6dd38,0,0,0,...) at taskqueue_thread_loop+0xe5 fork_exit(c08e0150,c0dd5340,c6b6dd38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b6dd70, ebp = 0 --- Tracing command kernel pid 0 tid 100024 td 0xc6da5d80 sched_switch(c6da5d80,0,104,e5fa9592,13,...) at sched_switch+0x279 mi_switch(104,0,c6da5d80,c6f2b0d8,c6b6aca4,...) at mi_switch+0x12a sleepq_switch(c6da5d80,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f2b0c0,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 msleep_spin(c6f2b0c0,c6f2b0d8,c0cb24d6,0,c6b6acf4,...) at msleep_spin+0x185 taskqueue_thread_loop(c0dd5340,c6b6ad38,0,0,0,...) at taskqueue_thread_loop+0xe5 fork_exit(c08e0150,c0dd5340,c6b6ad38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b6ad70, ebp = 0 --- Tracing command kernel pid 0 tid 100020 td 0xc6f376c0 sched_switch(c6f376c0,0,104,95ba8ee4,15,...) at sched_switch+0x279 mi_switch(104,0,c6f376c0,0,c6b5ec94,...) at mi_switch+0x12a sleepq_switch(c6f376c0,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f2b300,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 _sleep(c6f2b300,c6f2b318,0,c0cb24d6,0,...) at _sleep+0x2a2 taskqueue_thread_loop(c0e18988,c6b5ed38,0,0,0,...) at taskqueue_thread_loop+0x10b fork_exit(c08e0150,c0e18988,c6b5ed38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b5ed70, ebp = 0 --- Tracing command kernel pid 0 tid 100018 td 0xc6f37b40 sched_switch(c6f37b40,0,104,e5f6e7a4,13,...) at sched_switch+0x279 mi_switch(104,0,c6f37b40,0,c6b58c94,...) at mi_switch+0x12a sleepq_switch(c6f37b40,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6f2b580,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 _sleep(c6f2b580,c6f2b598,0,c0cb24d6,0,...) at _sleep+0x2a2 taskqueue_thread_loop(c0e04a78,c6b58d38,0,0,0,...) at taskqueue_thread_loop+0x10b fork_exit(c08e0150,c0e04a78,c6b58d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b58d70, ebp = 0 --- Tracing command kernel pid 0 tid 100016 td 0xc6d61480 sched_switch(c6d61480,0,104,9a4d7b53,15,...) at sched_switch+0x279 mi_switch(104,0,c6d61480,0,c6b52c94,...) at mi_switch+0x12a sleepq_switch(c6d61480,0,c0cbcce5,260,0,...) at sleepq_switch+0xcc sleepq_wait(c6d44e80,0,c0cb24d6,0,0,...) at sleepq_wait+0x39 _sleep(c6d44e80,c6d44e98,0,c0cb24d6,0,...) at _sleep+0x2a2 taskqueue_thread_loop(c0e17420,c6b52d38,0,0,0,...) at taskqueue_thread_loop+0x10b fork_exit(c08e0150,c0e17420,c6b52d38) at fork_exit+0x91 fork_trampoline() at fork_trampoline+0x8 --- trap 0, eip = 0, esp = 0xc6b52d70, ebp = 0 --- Tracing command kernel pid 0 tid 100000 td 0xc0e04490 sched_switch(c0e04490,0,104,66d6a42c,3409,...) at sched_switch+0x279 mi_switch(104,0,c0e04490,0,c1420d00,...) at mi_switch+0x12a sleepq_switch(c0e04490,0,c0cbcce5,283,0,...) at sleepq_switch+0xcc sleepq_timedwait(c0e041e0,44,c0cbb12d,0,0,...) at sleepq_timedwait+0x3e _sleep(c0e041e0,0,44,c0cbb12d,2710,...) at _sleep+0x272 scheduler(0,141ec00,141ec00,141e000,1425000,...) at scheduler+0x2e9 mi_startup() at mi_startup+0x96 begin() at begin+0x2c db:0:allt> call doadump Physical memory: 3439 MB Dumping 167 MB: 152 136 120 104 88 72 56 40 24 8 Dump complete = 0xf db:0:doadump> reset git diff master diff --git a/sys/conf/files b/sys/conf/files index 7793ec7..317e690 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2077,6 +2077,7 @@ kern/kern_poll.c optional device_polling kern/kern_priv.c standard kern/kern_proc.c standard kern/kern_prot.c standard +kern/kern_rangelock.c standard kern/kern_resource.c standard kern/kern_rmlock.c standard kern/kern_rwlock.c standard @@ -2768,6 +2769,7 @@ vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_phys.c standard +vm/vm_readwrite.c standard vm/vm_reserv.c standard vm/vm_unix.c standard vm/vm_zeroidle.c standard diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 2006099..d3eb99d 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -587,7 +588,7 @@ mdstart_swap(struct md_s *sc, struct bio *bp) { struct sf_buf *sf; int rv, offs, len, lastend; - vm_pindex_t i, lastp; + vm_pindex_t i, firstp, lastp; vm_page_t m; u_char *p; @@ -610,18 +611,26 @@ mdstart_swap(struct md_s *sc, struct bio *bp) * we're operating on complete aligned pages). */ offs = bp->bio_offset % PAGE_SIZE; + firstp = bp->bio_offset / PAGE_SIZE; lastp = (bp->bio_offset + bp->bio_length - 1) / PAGE_SIZE; lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1; + vm_page_t ma[lastp - firstp + 1]; + rv = VM_PAGER_OK; VM_OBJECT_LOCK(sc->object); vm_object_pip_add(sc->object, 1); - for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) { + for (i = firstp; i <= lastp; i++) { len = ((i == lastp) ? lastend : PAGE_SIZE) - offs; - m = vm_page_grab(sc->object, i, - VM_ALLOC_NORMAL|VM_ALLOC_RETRY); + /* + * Write cleans pages of the buffer, give it a + * priority. + */ + m = vm_page_grab(sc->object, i, (bp->bio_cmd == BIO_WRITE ? + VM_ALLOC_SYSTEM : VM_ALLOC_NORMAL) | VM_ALLOC_RETRY); VM_OBJECT_UNLOCK(sc->object); + ma[i - firstp] = m; sched_pin(); sf = sf_buf_alloc(m, SFB_CPUPRIVATE); VM_OBJECT_LOCK(sc->object); @@ -683,6 +692,12 @@ printf("wire_count %d busy %d flags %x hold_count %d act_count %d queue %d valid } vm_object_pip_subtract(sc->object, 1); vm_object_set_writeable_dirty(sc->object); + if (rv != VM_PAGER_ERROR && bp->bio_cmd == BIO_WRITE && + vm_page_count_severe()) { + vm_page_lock_queues(); + vm_pageout_flush(ma, lastp - firstp + 1, IO_SYNC); + vm_page_unlock_queues(); + } VM_OBJECT_UNLOCK(sc->object); return (rv != VM_PAGER_ERROR ? 0 : ENOSPC); } diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c new file mode 100644 index 0000000..86f0869 --- /dev/null +++ b/sys/kern/kern_rangelock.c @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2009 Konstantin Belousov + * 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 unmodified, 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. + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +uma_zone_t rl_entry_zone; + +static void +rangelock_sys_init(void) +{ + + rl_entry_zone = uma_zcreate("rl_entry", sizeof(struct rl_q_entry), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); +} +SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, rangelock_sys_init, NULL); + +void +rangelock_init(struct rangelock *lock) +{ + + TAILQ_INIT(&lock->rl_waiters); + lock->rl_currdep = NULL; +} + +void +rangelock_destroy(struct rangelock *lock) +{ + + KASSERT(TAILQ_EMPTY(&lock->rl_waiters), ("Dangling waiters")); +} + +static int +rangelock_incompatible(const struct rl_q_entry *e1, + const struct rl_q_entry *e2) +{ + + if ((e1->rl_q_flags & RL_LOCK_TYPE_MASK) == RL_LOCK_READ && + (e2->rl_q_flags & RL_LOCK_TYPE_MASK) == RL_LOCK_READ) + return (0); +#define IN_RANGE(a, e) (a >= e->rl_q_start && a < e->rl_q_end) + if (IN_RANGE(e1->rl_q_start, e2) || IN_RANGE(e2->rl_q_start, e1) || + IN_RANGE(e1->rl_q_end, e2) || IN_RANGE(e2->rl_q_end, e1)) + return (1); +#undef IN_RANGE + return (0); +} + +static void +rangelock_calc_block(struct rangelock *lock) +{ + struct rl_q_entry *entry, *entry1, *whead; + + if (lock->rl_currdep == TAILQ_FIRST(&lock->rl_waiters) && + lock->rl_currdep != NULL) + lock->rl_currdep = TAILQ_NEXT(lock->rl_currdep, rl_q_link); + for (entry = lock->rl_currdep; entry; + entry = TAILQ_NEXT(entry, rl_q_link)) { + TAILQ_FOREACH(entry1, &lock->rl_waiters, rl_q_link) { + if (rangelock_incompatible(entry, entry1)) + goto out; + if (entry1 == entry) + break; + } + } +out: + lock->rl_currdep = entry; + TAILQ_FOREACH(whead, &lock->rl_waiters, rl_q_link) { + if (whead == lock->rl_currdep) + break; + if (!(whead->rl_q_flags & RL_LOCK_GRANTED)) { + whead->rl_q_flags |= RL_LOCK_GRANTED; + wakeup(whead); + } + } +} + +static void +rangelock_unlock_vp_locked(struct vnode *vp, struct rl_q_entry *entry) +{ + + ASSERT_VI_LOCKED(vp, "rangelock"); + KASSERT(entry != vp->v_rl.rl_currdep, ("stuck currdep")); + TAILQ_REMOVE(&vp->v_rl.rl_waiters, entry, rl_q_link); + rangelock_calc_block(&vp->v_rl); + VI_UNLOCK(vp); + uma_zfree(rl_entry_zone, entry); +} + +void +rangelock_unlock(struct vnode *vp, void *cookie) +{ + struct rl_q_entry *entry; + + entry = cookie; + VI_LOCK(vp); + rangelock_unlock_vp_locked(vp, entry); +} + +void * +rangelock_unlock_range(struct vnode *vp, void *cookie, off_t base, size_t len) +{ + struct rl_q_entry *entry; + + entry = cookie; + VI_LOCK(vp); + KASSERT(entry->rl_q_flags & RL_LOCK_GRANTED, ("XXX")); + KASSERT(entry->rl_q_start == base, ("XXX")); + KASSERT(entry->rl_q_end >= base + len, ("XXX")); + if (entry->rl_q_end == base + len) { + rangelock_unlock_vp_locked(vp, cookie); + return (NULL); + } + entry->rl_q_end = base + len; + rangelock_calc_block(&vp->v_rl); + VI_UNLOCK(vp); + return (cookie); +} + +static void * +rangelock_enqueue(struct vnode *vp, struct rl_q_entry *entry) +{ + + VI_LOCK(vp); + TAILQ_INSERT_TAIL(&vp->v_rl.rl_waiters, entry, rl_q_link); + if (vp->v_rl.rl_currdep == NULL) + vp->v_rl.rl_currdep = entry; + rangelock_calc_block(&vp->v_rl); + while (!(entry->rl_q_flags & RL_LOCK_GRANTED)) + msleep(entry, &vp->v_interlock, 0, "range", 0); + VI_UNLOCK(vp); + return (entry); +} + +void * +rangelock_rlock(struct vnode *vp, off_t base, size_t len) +{ + struct rl_q_entry *entry; + + entry = uma_zalloc(rl_entry_zone, M_WAITOK); + entry->rl_q_flags = RL_LOCK_READ; + entry->rl_q_start = base; + entry->rl_q_end = base + len; + return (rangelock_enqueue(vp, entry)); +} + +void * +rangelock_wlock(struct vnode *vp, off_t base, size_t len) +{ + struct rl_q_entry *entry; + + entry = uma_zalloc(rl_entry_zone, M_WAITOK); + entry->rl_q_flags = RL_LOCK_WRITE; + entry->rl_q_start = base; + entry->rl_q_end = base + len; + return (rangelock_enqueue(vp, entry)); +} diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 1ab263c..d249e44 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -71,8 +71,8 @@ static int write_behind = 1; SYSCTL_INT(_vfs, OID_AUTO, write_behind, CTLFLAG_RW, &write_behind, 0, "Cluster write-behind; 0: disable, 1: enable, 2: backed off"); -static int read_max = 8; -SYSCTL_INT(_vfs, OID_AUTO, read_max, CTLFLAG_RW, &read_max, 0, +int vfs_read_max = 8; +SYSCTL_INT(_vfs, OID_AUTO, read_max, CTLFLAG_RW, &vfs_read_max, 0, "Cluster read-ahead max block count"); /* Page expended to mark partially backed buffers */ @@ -109,7 +109,7 @@ cluster_read(vp, filesize, lblkno, size, cred, totread, seqcount, bpp) */ racluster = vp->v_mount->mnt_iosize_max / size; maxra = seqcount; - maxra = min(read_max, maxra); + maxra = min(vfs_read_max, maxra); maxra = min(nbuf/8, maxra); if (((u_quad_t)(lblkno + maxra + 1) * size) > filesize) maxra = (filesize / size) - lblkno; @@ -803,7 +803,9 @@ cluster_wbuild(vp, size, start_lbn, len) (tbp->b_bcount != tbp->b_bufsize) || (tbp->b_bcount != size) || (len == 1) || - ((bp = getpbuf(&cluster_pbuf_freecnt)) == NULL)) { + ((bp = (vp->v_vflag & VV_MD) ? + trypbuf(&cluster_pbuf_freecnt) : + getpbuf(&cluster_pbuf_freecnt)) == NULL)) { totalwritten += tbp->b_bufsize; bawrite(tbp); ++start_lbn; diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index b80d03d..3636360 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -77,6 +77,8 @@ static int dirent_exists(struct vnode *vp, const char *dirname, #define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) +static int vop_stdextend(struct vop_extend_args *ap); + /* * This vnode table stores what we want to do if the filesystem doesn't * implement a particular VOP. @@ -118,6 +120,7 @@ struct vop_vector default_vnodeops = { .vop_unlock = vop_stdunlock, .vop_vptocnp = vop_stdvptocnp, .vop_vptofh = vop_stdvptofh, + .vop_extend = vop_stdextend, }; /* @@ -825,6 +828,23 @@ out: return (error); } +static int +vop_stdextend(struct vop_extend_args *ap) +{ + struct vattr vattr, oattr; + int error; + + + error = VOP_GETATTR(ap->a_vp, &oattr, ap->a_cred); + if (error != 0) + return (error); + if (oattr.va_size >= ap->a_size) + return (0); + VATTR_NULL(&vattr); + vattr.va_size = ap->a_size; + return (VOP_SETATTR(ap->a_vp, &vattr, ap->a_cred)); +} + /* * vfs default ops * used to fill the vfs function table to get reasonable default return values. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index daaa5b1..245d00e 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -861,6 +861,7 @@ vdestroy(struct vnode *vp) /* XXX Elsewhere we can detect an already freed vnode via NULL v_op. */ vp->v_op = NULL; #endif + rangelock_destroy(&vp->v_rl); lockdestroy(vp->v_vnlock); mtx_destroy(&vp->v_interlock); mtx_destroy(BO_MTX(bo)); @@ -1015,6 +1016,7 @@ alloc: if ((mp->mnt_kern_flag & MNTK_NOKNOTE) != 0) vp->v_vflag |= VV_NOKNOTE; } + rangelock_init(&vp->v_rl); *vpp = vp; return (0); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index d0b713c..bc88b8a 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -37,12 +37,14 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include #include +#include #include #include #include @@ -62,6 +64,13 @@ __FBSDID("$FreeBSD$"); #include +#include +#include + +static int vmio_enabled = 1; +SYSCTL_INT(_vfs, OID_AUTO, vmio_enabled, CTLFLAG_RW, &vmio_enabled, 0, + "Use vm pages copyin/out instead of vops for read/write"); + static fo_rdwr_t vn_read; static fo_rdwr_t vn_write; static fo_truncate_t vn_truncate; @@ -83,6 +92,9 @@ struct fileops vnops = { .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE }; +static int vn_write_chunk(struct vnode *, struct uio *, struct ucred *, + struct ucred *, int); + int vn_open(ndp, flagp, cmode, fp) struct nameidata *ndp; @@ -275,17 +287,14 @@ vn_writechk(vp) * Vnode close call */ int -vn_close(vp, flags, file_cred, td) - register struct vnode *vp; - int flags; - struct ucred *file_cred; - struct thread *td; +vn_close(struct vnode *vp, int flags, struct ucred *file_cred, + struct thread *td) { - struct mount *mp; + struct mount *mp, *mp1; int error, lock_flags; - if (!(flags & FWRITE) && vp->v_mount != NULL && - vp->v_mount->mnt_kern_flag & MNTK_EXTENDED_SHARED) + if (!(flags & FWRITE) && (mp1 = vp->v_mount) != NULL && + MNT_SHARED_WRITES(mp1)) lock_flags = LK_SHARED; else lock_flags = LK_EXCLUSIVE; @@ -333,7 +342,7 @@ sequential_heuristic(struct uio *uio, struct file *fp) * closely related to the best I/O size for real disks than * to any block size used by software. */ - fp->f_seqcount += howmany(uio->uio_resid, 16384); + fp->f_seqcount += howmany(uio->uio_resid, FRA_BLOCK_SZ); if (fp->f_seqcount > IO_SEQMAX) fp->f_seqcount = IO_SEQMAX; return (fp->f_seqcount << IO_SEQSHIFT); @@ -351,76 +360,71 @@ sequential_heuristic(struct uio *uio, struct file *fp) * Package up an I/O request on a vnode into a uio and do it. */ int -vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred, - aresid, td) - enum uio_rw rw; - struct vnode *vp; - void *base; - int len; - off_t offset; - enum uio_seg segflg; - int ioflg; - struct ucred *active_cred; - struct ucred *file_cred; - int *aresid; - struct thread *td; +vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, + enum uio_seg segflg, int ioflg, struct ucred *active_cred, + struct ucred *file_cred, int *aresid, struct thread *td) { struct uio auio; struct iovec aiov; struct mount *mp; struct ucred *cred; + void *rl_cookie; int error, lock_flags; VFS_ASSERT_GIANT(vp->v_mount); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = base; + aiov.iov_len = len; + auio.uio_resid = len; + auio.uio_offset = offset; + auio.uio_segflg = segflg; + auio.uio_rw = rw; + auio.uio_td = td; + error = 0; + if ((ioflg & IO_NODELOCKED) == 0) { + if (rw == UIO_READ) + rl_cookie = rangelock_rlock(vp, offset, len); + else + rl_cookie = rangelock_wlock(vp, offset, len); mp = NULL; if (rw == UIO_WRITE) { if (vp->v_type != VCHR && (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) - return (error); + goto out; if (MNT_SHARED_WRITES(mp) || - ((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount))) { + ((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount))) lock_flags = LK_SHARED; - } else { + else lock_flags = LK_EXCLUSIVE; - } - vn_lock(vp, lock_flags | LK_RETRY); } else - vn_lock(vp, LK_SHARED | LK_RETRY); + lock_flags = LK_SHARED; + vn_lock(vp, lock_flags | LK_RETRY); + } else + rl_cookie = NULL; - } ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held"); - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - aiov.iov_base = base; - aiov.iov_len = len; - auio.uio_resid = len; - auio.uio_offset = offset; - auio.uio_segflg = segflg; - auio.uio_rw = rw; - auio.uio_td = td; - error = 0; #ifdef MAC if ((ioflg & IO_NOMACCHECK) == 0) { - if (rw == UIO_READ) - error = mac_vnode_check_read(active_cred, file_cred, - vp); - else + if (rw == UIO_WRITE) error = mac_vnode_check_write(active_cred, file_cred, vp); } #endif if (error == 0) { - if (file_cred) + if (file_cred != NULL) cred = file_cred; else cred = active_cred; if (rw == UIO_READ) - error = VOP_READ(vp, &auio, ioflg, cred); + error = vn_read_chunk(vp, &auio, active_cred, cred, + ioflg | IO_NODELOCKED); else - error = VOP_WRITE(vp, &auio, ioflg, cred); + error = vn_write_chunk(vp, &auio, active_cred, cred, + ioflg | IO_NODELOCKED); } if (aresid) *aresid = auio.uio_resid; @@ -428,10 +432,13 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred, if (auio.uio_resid && error == 0) error = EIO; if ((ioflg & IO_NODELOCKED) == 0) { - if (rw == UIO_WRITE && vp->v_type != VCHR) - vn_finished_write(mp); VOP_UNLOCK(vp, 0); + if (mp != NULL) + vn_finished_write(mp); } + out: + if (rl_cookie != NULL) + rangelock_unlock(vp, rl_cookie); return (error); } @@ -493,68 +500,148 @@ vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, active_cred, return (error); } +static struct mtx * +vn_lock_foffset(struct file *fp) +{ + struct mtx *mtxp; + + mtxp = mtx_pool_find(mtxpool_sleep, fp); + mtx_lock(mtxp); + while (fp->f_vnread_flags & FOFFSET_LOCKED) { + fp->f_vnread_flags |= FOFFSET_LOCK_WAITING; + msleep(&fp->f_vnread_flags, mtxp, PUSER -1, + "vnread offlock", 0); + } + fp->f_vnread_flags |= FOFFSET_LOCKED; + mtx_unlock(mtxp); + return (mtxp); +} + +static void +vn_unlock_foffset(struct file *fp, struct mtx *mtxp) +{ + + mtx_lock(mtxp); + if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) + wakeup(&fp->f_vnread_flags); + fp->f_vnread_flags = 0; + mtx_unlock(mtxp); +} + +int +vn_read_chunk(struct vnode *vp, struct uio *uio, struct ucred *active_cred, + struct ucred *fcred, int ioflag) +{ + int error, vfslocked; + + error = 0; + vfslocked = 0; /* gcc */ + + if ((ioflag & IO_NODELOCKED) == 0) { + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY); + } + +#ifdef MAC + if ((ioflag & IO_NOMACCHECK) == 0) + error = mac_vnode_check_read(active_cred, fcred, vp); +#endif + if (error == 0) { + if (!vmio_enabled || + (error = vnode_pager_read(vp, uio, ioflag)) == EOPNOTSUPP) + error = VOP_READ(vp, uio, ioflag, fcred); + } + if ((ioflag & IO_NODELOCKED) == 0) { + VOP_UNLOCK(vp, 0); + VFS_UNLOCK_GIANT(vfslocked); + } + return (error); +} + /* * File table vnode read routine. */ static int -vn_read(fp, uio, active_cred, flags, td) - struct file *fp; - struct uio *uio; - struct ucred *active_cred; - struct thread *td; - int flags; +vn_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, + struct thread *td) { struct vnode *vp; - int error, ioflag; struct mtx *mtxp; - int vfslocked; + void *rl_cookie; + int ioflag; + int error; KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); - mtxp = NULL; - vp = fp->f_vnode; ioflag = 0; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; if (fp->f_flag & O_DIRECT) ioflag |= IO_DIRECT; - vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vp = fp->f_vnode; + /* * According to McKusick the vn lock was protecting f_offset here. * It is now protected by the FOFFSET_LOCKED flag. */ if ((flags & FOF_OFFSET) == 0) { - mtxp = mtx_pool_find(mtxpool_sleep, fp); - mtx_lock(mtxp); - while(fp->f_vnread_flags & FOFFSET_LOCKED) { - fp->f_vnread_flags |= FOFFSET_LOCK_WAITING; - msleep(&fp->f_vnread_flags, mtxp, PUSER -1, - "vnread offlock", 0); - } - fp->f_vnread_flags |= FOFFSET_LOCKED; - mtx_unlock(mtxp); - vn_lock(vp, LK_SHARED | LK_RETRY); + mtxp = vn_lock_foffset(fp); uio->uio_offset = fp->f_offset; } else - vn_lock(vp, LK_SHARED | LK_RETRY); - + mtxp = NULL; /* gcc */ + if (vp->v_type == VREG) + rl_cookie = rangelock_rlock(vp, uio->uio_offset, + uio->uio_resid); + else + rl_cookie = NULL; ioflag |= sequential_heuristic(uio, fp); + error = vn_read_chunk(vp, uio, active_cred, fp->f_cred, ioflag); + fp->f_nextoff = uio->uio_offset; + if (rl_cookie != NULL) + rangelock_unlock(vp, rl_cookie); + if ((flags & FOF_OFFSET) == 0) { + fp->f_offset = uio->uio_offset; + vn_unlock_foffset(fp, mtxp); + } + return (error); +} +static int +vn_write_chunk(struct vnode *vp, struct uio *uio, struct ucred *active_cred, + struct ucred *fcred, int ioflag) +{ + struct mount *mp, *mp1; + int error, lock_flags, vfslocked; + + mp = NULL; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + if (vp->v_type == VREG) + bwillwrite(); + if (vp->v_type != VCHR && + (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) + goto unlock; + + if (MNT_SHARED_WRITES(mp) || + (mp == NULL && (mp1 = vp->v_mount) != NULL && + MNT_SHARED_WRITES(mp1))) + lock_flags = LK_SHARED; + else + lock_flags = LK_EXCLUSIVE; + vn_lock(vp, lock_flags | LK_RETRY); #ifdef MAC - error = mac_vnode_check_read(active_cred, fp->f_cred, vp); - if (error == 0) + error = mac_vnode_check_write(active_cred, fcred, vp); +#else + error = 0; #endif - error = VOP_READ(vp, uio, ioflag, fp->f_cred); - if ((flags & FOF_OFFSET) == 0) { - fp->f_offset = uio->uio_offset; - mtx_lock(mtxp); - if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) - wakeup(&fp->f_vnread_flags); - fp->f_vnread_flags = 0; - mtx_unlock(mtxp); + if (error == 0) { + if (!vmio_enabled || + (error = vnode_pager_write(vp, uio, ioflag)) == EOPNOTSUPP) + error = VOP_WRITE(vp, uio, ioflag, fcred); } - fp->f_nextoff = uio->uio_offset; VOP_UNLOCK(vp, 0); + if (vp->v_type != VCHR) + vn_finished_write(mp); +unlock: VFS_UNLOCK_GIANT(vfslocked); return (error); } @@ -563,24 +650,17 @@ vn_read(fp, uio, active_cred, flags, td) * File table vnode write routine. */ static int -vn_write(fp, uio, active_cred, flags, td) - struct file *fp; - struct uio *uio; - struct ucred *active_cred; - struct thread *td; - int flags; +vn_write(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, + struct thread *td) { struct vnode *vp; - struct mount *mp; - int error, ioflag, lock_flags; - int vfslocked; + struct mtx *mtxp; + void *rl_cookie; + int error, ioflag; KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); vp = fp->f_vnode; - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - if (vp->v_type == VREG) - bwillwrite(); ioflag = IO_UNIT; if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) ioflag |= IO_APPEND; @@ -591,36 +671,32 @@ vn_write(fp, uio, active_cred, flags, td) if ((fp->f_flag & O_FSYNC) || (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) ioflag |= IO_SYNC; - mp = NULL; - if (vp->v_type != VCHR && - (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) - goto unlock; - - if ((MNT_SHARED_WRITES(mp) || - ((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount))) && - (flags & FOF_OFFSET) != 0) { - lock_flags = LK_SHARED; - } else { - lock_flags = LK_EXCLUSIVE; - } - - vn_lock(vp, lock_flags | LK_RETRY); - if ((flags & FOF_OFFSET) == 0) + if ((flags & FOF_OFFSET) == 0) { + mtxp = vn_lock_foffset(fp); uio->uio_offset = fp->f_offset; + } else + mtxp = NULL; /* gcc */ ioflag |= sequential_heuristic(uio, fp); -#ifdef MAC - error = mac_vnode_check_write(active_cred, fp->f_cred, vp); - if (error == 0) -#endif - error = VOP_WRITE(vp, uio, ioflag, fp->f_cred); - if ((flags & FOF_OFFSET) == 0) + if (vp->v_type == VREG) { + if ((ioflag & IO_APPEND) || !(flags & FOF_OFFSET)) + /* + * For appenders, punt and lock the whole + * range. It also protects f_offset. + */ + rl_cookie = rangelock_wlock(vp, 0, (size_t)-1); + else + rl_cookie = rangelock_wlock(vp, uio->uio_offset, + uio->uio_resid); + } else + rl_cookie = NULL; + error = vn_write_chunk(vp, uio, active_cred, fp->f_cred, ioflag); + if (rl_cookie != NULL) + rangelock_unlock(vp, rl_cookie); + if ((flags & FOF_OFFSET) == 0) { fp->f_offset = uio->uio_offset; + vn_unlock_foffset(fp, mtxp); + } fp->f_nextoff = uio->uio_offset; - VOP_UNLOCK(vp, 0); - if (vp->v_type != VCHR) - vn_finished_write(mp); -unlock: - VFS_UNLOCK_GIANT(vfslocked); return (error); } @@ -628,25 +704,29 @@ unlock: * File table truncate routine. */ static int -vn_truncate(fp, length, active_cred, td) - struct file *fp; - off_t length; - struct ucred *active_cred; - struct thread *td; +vn_truncate(struct file *fp, off_t length, struct ucred *active_cred, + struct thread *td) { struct vattr vattr; struct mount *mp; struct vnode *vp; + void *rl_cookie; int vfslocked; int error; vp = fp->f_vnode; + + /* + * Lock the range where the shortening take place. Increase of + * file size does not need rangelock, but it is faster to lock + * the range then call VOP_GETATTR to get the current size and + * deal with races. + */ + rl_cookie = rangelock_wlock(vp, length, -1); vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = vn_start_write(vp, &mp, V_WAIT | PCATCH); - if (error) { - VFS_UNLOCK_GIANT(vfslocked); - return (error); - } + if (error) + goto out1; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (vp->v_type == VDIR) { error = EISDIR; @@ -666,7 +746,9 @@ vn_truncate(fp, length, active_cred, td) out: VOP_UNLOCK(vp, 0); vn_finished_write(mp); +out1: VFS_UNLOCK_GIANT(vfslocked); + rangelock_unlock(vp, rl_cookie); return (error); } diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index c9f20e3..27e298c 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -611,3 +611,12 @@ vop_vptocnp { INOUT char *buf; INOUT int *buflen; }; + +%% extend vp L L L + +vop_extend { + IN struct vnode *vp; + IN struct ucred *cred; + IN u_quad_t size; + IN int flags; +}; diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 8f3b1b2..e6fdf7e 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -257,6 +257,8 @@ extern const char *buf_wmesg; /* Default buffer lock message */ #include /* XXX for curthread */ #include +extern int vfs_read_max; + /* * Initialize a lock. */ diff --git a/sys/sys/file.h b/sys/sys/file.h index 8ad30a5..b9f52ae 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -141,6 +141,8 @@ struct file { #define FOFFSET_LOCKED 0x1 #define FOFFSET_LOCK_WAITING 0x2 +#define FRA_BLOCK_SZ 16384 + #endif /* _KERNEL || _WANT_FILE */ /* diff --git a/sys/sys/proc.h b/sys/sys/proc.h index dd9efae..0ceab2e 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -354,7 +354,7 @@ do { \ #define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */ #define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */ #define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */ -#define TDP_UNUSED80 0x00000080 /* available. */ +#define TDP_VMIO 0x00000080 /* Busied pages for vnode_pager io. */ #define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ #define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ diff --git a/sys/sys/rangelock.h b/sys/sys/rangelock.h new file mode 100644 index 0000000..5ec6433 --- /dev/null +++ b/sys/sys/rangelock.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2009 Konstantin Belousov + * All rights reserved. + * + * $FreeBSD$ + */ + +#ifndef _SYS_RANGELOCK_H +#define _SYS_RANGELOCK_H + +#include +#include +#include +#include +#include + +#ifdef _KERNEL + +struct vnode; + +struct rl_q_entry +{ + TAILQ_ENTRY(rl_q_entry) rl_q_link; + size_t rl_q_start, rl_q_end; + int rl_q_flags; +}; + +#define RL_LOCK_READ 0x0001 +#define RL_LOCK_WRITE 0x0002 +#define RL_LOCK_TYPE_MASK 0x0003 +#define RL_LOCK_GRANTED 0x0004 + +struct rangelock +{ + TAILQ_HEAD(, rl_q_entry) rl_waiters; + struct rl_q_entry *rl_currdep; +}; + +void rangelock_init(struct rangelock *lock); +void rangelock_destroy(struct rangelock *lock); +void rangelock_unlock(struct vnode *vp, void *cookie); +void *rangelock_unlock_range(struct vnode *vp, void *cookie, off_t base, + size_t len); +void *rangelock_rlock(struct vnode *vp, off_t base, size_t len); +void *rangelock_wlock(struct vnode *vp, off_t base, size_t len); +#endif + +#endif diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 4c84ea3..6ed52ef 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,8 @@ struct vnode { */ struct vpollinfo *v_pollinfo; /* G Poll events, p for *v_pi */ struct label *v_label; /* MAC label for vnode */ - struct lockf *v_lockf; /* Byte-level lock list */ + struct lockf *v_lockf; /* Byte-level adv lock list */ + struct rangelock v_rl; /* Byte-range lock */ }; #endif /* defined(_KERNEL) || defined(_KVM_VNODE) */ @@ -655,6 +657,8 @@ int vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, size_t len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, size_t *aresid, struct thread *td); +int vn_read_chunk(struct vnode *vp, struct uio *uio, + struct ucred *active_cred, struct ucred *f_cred, int ioflag); int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, struct ucred *file_cred, struct thread *td); int vn_start_write(struct vnode *vp, struct mount **mpp, int flags); diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index a12f96e..9aca6c1 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -634,7 +634,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, if (lastlbn < NDADDR && lastlbn < lbn) { nb = lastlbn; osize = blksize(fs, ip, nb); - if (osize < fs->fs_bsize && osize > 0) { + if (osize < fs->fs_bsize && osize > 0 && dp->di_db[nb] != 0) { UFS_LOCK(ump); error = ffs_realloccg(ip, nb, dp->di_db[nb], ffs_blkpref_ufs2(ip, lastlbn, (int)nb, @@ -701,9 +701,17 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, nsize, osize, bp); } } else { - if (ip->i_size < smalllblktosize(fs, lbn + 1)) + if (ip->i_size < smalllblktosize(fs, lbn)) nsize = fragroundup(fs, size); - else + else if (ip->i_size < smalllblktosize(fs, lbn + 1)) { + /* + * Allocate entire tail of the file. + * Write may cover subpart of the extended + * area. + */ + nsize = fragroundup(fs, max(size, + blkoff(fs, ip->i_size))); + } else nsize = fs->fs_bsize; UFS_LOCK(ump); error = ffs_alloc(ip, lbn, diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 4d652c1..a3e890e 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -1651,7 +1651,7 @@ softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp) ufs2_daddr_t newblkno; /* disk block number being added */ ufs2_daddr_t oldblkno; /* previous block number, 0 unless frag */ long newsize; /* size of new block */ - long oldsize; /* size of new block */ + long oldsize; /* size of old block */ struct buf *bp; /* bp for allocated block */ { struct allocdirect *adp, *oldadp; @@ -1765,8 +1765,8 @@ allocdirect_merge(adphead, newadp, oldadp) if (newadp->ad_oldblkno != oldadp->ad_newblkno || newadp->ad_oldsize != oldadp->ad_newsize || newadp->ad_lbn >= NDADDR) - panic("%s %jd != new %jd || old size %ld != new %ld", - "allocdirect_merge: old blkno", + panic("allocdirect_merge: old blkno" + " %jd != new %jd || old size %ld != new %ld", (intmax_t)newadp->ad_oldblkno, (intmax_t)oldadp->ad_newblkno, newadp->ad_oldsize, oldadp->ad_newsize); @@ -2813,7 +2813,11 @@ handle_workitem_freeblocks(freeblks, flags) #ifdef INVARIANTS if (freeblks->fb_chkcnt != blocksreleased && ((fs->fs_flags & FS_UNCLEAN) == 0 || (flags & LK_NOWAIT) != 0)) - printf("handle_workitem_freeblocks: block count\n"); + printf("handle_workitem_freeblocks: ino %jd block count " + "check %jd real %jd diff %jd\n", + (intmax_t)freeblks->fb_previousinum, + (intmax_t)freeblks->fb_chkcnt, (intmax_t)blocksreleased, + (intmax_t)(freeblks->fb_chkcnt - blocksreleased)); if (allerror) softdep_error("handle_workitem_freeblks", allerror); #endif /* INVARIANTS */ diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 464a761..e864692 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -119,7 +119,7 @@ static vop_listextattr_t ffs_listextattr; static vop_openextattr_t ffs_openextattr; static vop_setextattr_t ffs_setextattr; static vop_vptofh_t ffs_vptofh; - +static vop_extend_t ffs_extend; /* Global vfs data structures for ufs. */ struct vop_vector ffs_vnodeops1 = { @@ -131,6 +131,7 @@ struct vop_vector ffs_vnodeops1 = { .vop_reallocblks = ffs_reallocblks, .vop_write = ffs_write, .vop_vptofh = ffs_vptofh, + .vop_extend = ffs_extend, }; struct vop_vector ffs_fifoops1 = { @@ -156,6 +157,7 @@ struct vop_vector ffs_vnodeops2 = { .vop_openextattr = ffs_openextattr, .vop_setextattr = ffs_setextattr, .vop_vptofh = ffs_vptofh, + .vop_extend = ffs_extend, }; struct vop_vector ffs_fifoops2 = { @@ -1783,3 +1785,66 @@ vop_vptofh { ufhp->ufid_gen = ip->i_gen; return (0); } + +static int +ffs_extend(struct vop_extend_args *ap) +{ + struct vnode *vp; + struct inode *ip; + struct buf *bp; + struct fs *fs; + off_t osize, xosize; + u_quad_t size; + ufs_lbn_t lastlbn; + ufs2_daddr_t nb; + int error, flags; + + vp = ap->a_vp; + ip = VTOI(vp); + size = ap->a_size; + osize = ip->i_size; + if (osize >= size) + return (0); + + vnode_pager_setsize(vp, size); + fs = ip->i_fs; + flags = ap->a_flags & IO_SYNC; + if (flags != 0) + goto slow; + + lastlbn = lblkno(fs, osize); + if (lastlbn < NDADDR) { + xosize = fragroundup(fs, blkoff(fs, osize)); + if (xosize < fs->fs_bsize && xosize > 0) { + if (ip->i_ump->um_fstype == UFS1) + nb = ip->i_din1->di_db[lastlbn]; + else + nb = ip->i_din2->di_db[lastlbn]; + /* Need to extend fragment */ + if (nb != 0) + goto slow; + } + } + ip->i_size = size; + DIP_SET(ip, i_size, size); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + return (0); + + slow: + error = UFS_BALLOC(vp, size - 1, 1, ap->a_cred, flags|BA_CLRBUF, &bp); + if (error) { + vnode_pager_setsize(vp, osize); + return (error); + } + ip->i_size = size; + DIP_SET(ip, i_size, size); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (bp->b_bufsize == fs->fs_bsize) + bp->b_flags |= B_CLUSTEROK; + if (flags & IO_SYNC) { + bwrite(bp); + error = ffs_update(vp, 1); + } else + bawrite(bp); + return (error); +} diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 9d4d93d..52c08f6 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -2072,7 +2072,8 @@ ufs_readdir(ap) uio->uio_iov->iov_len = count; # if (BYTE_ORDER == LITTLE_ENDIAN) if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) { - error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); + error = vn_read_chunk(ap->a_vp, uio, ap->a_cred, + ap->a_cred, IO_NODELOCKED); } else { struct dirent *dp, *edp; struct uio auio; @@ -2088,7 +2089,8 @@ ufs_readdir(ap) aiov.iov_len = count; dirbuf = malloc(count, M_TEMP, M_WAITOK); aiov.iov_base = dirbuf; - error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); + error = vn_read_chunk(ap->a_vp, &auio, ap->a_cred, + ap->a_cred, IO_NODELOCKED); if (error == 0) { readcnt = count - auio.uio_resid; edp = (struct dirent *)&dirbuf[readcnt]; @@ -2110,7 +2112,8 @@ ufs_readdir(ap) free(dirbuf, M_TEMP); } # else - error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); + error = vn_read_chunk(ap->a_vp, uio, ap->a_cred, + ap->a_cred, IO_NODELOCKED); # endif if (!error && ap->a_ncookies != NULL) { struct dirent* dpStart; diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index ad6087e..e24c62b 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -84,5 +84,8 @@ void vm_thread_dispose(struct thread *td); int vm_thread_new(struct thread *td, int pages); void vm_thread_swapin(struct thread *td); void vm_thread_swapout(struct thread *td); +int vnode_pager_read(struct vnode *vp, struct uio *uio, int ioflags); +int vnode_pager_write(struct vnode *vp, struct uio *uio, int ioflags); + #endif /* _KERNEL */ #endif /* !_VM_EXTERN_H_ */ diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 0a5a412..fca7d5a 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -157,18 +157,22 @@ static void unlock_and_deallocate(struct faultstate *fs) { - vm_object_pip_wakeup(fs->object); - VM_OBJECT_UNLOCK(fs->object); - if (fs->object != fs->first_object) { - VM_OBJECT_LOCK(fs->first_object); - vm_page_lock_queues(); - vm_page_free(fs->first_m); - vm_page_unlock_queues(); - vm_object_pip_wakeup(fs->first_object); - VM_OBJECT_UNLOCK(fs->first_object); - fs->first_m = NULL; + if (fs->object != NULL) { + vm_object_pip_wakeup(fs->object); + VM_OBJECT_UNLOCK(fs->object); + if (fs->object != fs->first_object && + fs->first_object != NULL) { + VM_OBJECT_LOCK(fs->first_object); + vm_page_lock_queues(); + vm_page_free(fs->first_m); + vm_page_unlock_queues(); + vm_object_pip_wakeup(fs->first_object); + VM_OBJECT_UNLOCK(fs->first_object); + fs->first_m = NULL; + } + vm_object_deallocate(fs->first_object); + fs->object = fs->first_object = NULL; } - vm_object_deallocate(fs->first_object); unlock_map(fs); if (fs->vp != NULL) { vput(fs->vp); @@ -219,14 +223,15 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int faultcount, ahead, behind; struct faultstate fs; struct vnode *vp; + struct thread *td; int locked, error; hardfault = 0; growstack = TRUE; PCPU_INC(cnt.v_vm_faults); - fs.vp = NULL; - fs.vfslocked = 0; + memset(&fs, 0, sizeof(fs)); faultcount = behind = 0; + td = curthread; RetryFault:; @@ -241,11 +246,14 @@ RetryFault:; if (growstack && result == KERN_INVALID_ADDRESS && map != kernel_map) { result = vm_map_growstack(curproc, vaddr); - if (result != KERN_SUCCESS) + if (result != KERN_SUCCESS) { + unlock_and_deallocate(&fs); return (KERN_FAILURE); + } growstack = FALSE; goto RetryFault; } + unlock_and_deallocate(&fs); return (result); } @@ -367,7 +375,8 @@ RetryFault:; */ vm_page_busy(fs.m); if (fs.m->valid != VM_PAGE_BITS_ALL && - fs.m->object != kernel_object && fs.m->object != kmem_object) { + fs.m->object != kernel_object && + fs.m->object != kmem_object) { goto readrest; } @@ -523,7 +532,7 @@ vnode_lock: locked = LK_SHARED; /* Do not sleep for vnode lock while fs.m is busy */ error = vget(vp, locked | LK_CANRECURSE | - LK_NOWAIT, curthread); + LK_NOWAIT, td); if (error != 0) { int vfslocked; @@ -533,7 +542,7 @@ vnode_lock: release_page(&fs); unlock_and_deallocate(&fs); error = vget(vp, locked | LK_RETRY | - LK_CANRECURSE, curthread); + LK_CANRECURSE, td); vdrop(vp); fs.vp = vp; fs.vfslocked = vfslocked; @@ -937,9 +946,9 @@ vnode_locked: */ unlock_and_deallocate(&fs); if (hardfault) - curthread->td_ru.ru_majflt++; + td->td_ru.ru_majflt++; else - curthread->td_ru.ru_minflt++; + td->td_ru.ru_minflt++; return (KERN_SUCCESS); } diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index c6bcfa0..0ddb6e0 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -731,6 +731,10 @@ vm_page_remove(vm_page_t m) m->oflags &= ~VPO_BUSY; vm_page_flash(m); } + if (m->flags & PG_WRITEDIRTY) { + m->flags &= ~PG_WRITEDIRTY; + vm_writedirty_cleaned(1); + } mtx_assert(&vm_page_queue_mtx, MA_OWNED); /* @@ -1188,6 +1192,19 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) return (m); } +void +vm_wait_queue_free(const char *wmsg) +{ + + mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); + if (!vm_pages_needed) { + vm_pages_needed = 1; + wakeup(&vm_pages_needed); + } + msleep(&cnt.v_free_count, &vm_page_queue_free_mtx, PDROP | PVM, wmsg, + 0); +} + /* * vm_wait: (also see VM_WAIT macro) * @@ -1203,14 +1220,8 @@ vm_wait(void) vm_pageout_pages_needed = 1; msleep(&vm_pageout_pages_needed, &vm_page_queue_free_mtx, PDROP | PSWP, "VMWait", 0); - } else { - if (!vm_pages_needed) { - vm_pages_needed = 1; - wakeup(&vm_pages_needed); - } - msleep(&cnt.v_free_count, &vm_page_queue_free_mtx, PDROP | PVM, - "vmwait", 0); - } + } else + vm_wait_queue_free("vmwait"); } /* @@ -1686,6 +1697,11 @@ vm_page_cache(vm_page_t m) if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT) pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT); + if (m->flags & PG_WRITEDIRTY) { + m->flags &= ~PG_WRITEDIRTY; + vm_writedirty_cleaned(1); + } + /* * Insert the page into the object's collection of cached pages * and the physical memory allocator's cache/free page queues. diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 662af98..0d081e2 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -195,6 +195,7 @@ extern struct vpglocks vm_page_queue_free_lock; #define PG_WINATCFLS 0x0004 /* flush dirty page on inactive q */ #define PG_FICTITIOUS 0x0008 /* physical page doesn't exist (O) */ #define PG_WRITEABLE 0x0010 /* page is mapped writeable */ +#define PG_WRITEDIRTY 0x0020 /* dirtied by vmio write */ #define PG_ZERO 0x0040 /* page is zeroed */ #define PG_REFERENCED 0x0080 /* page has been referenced */ #define PG_UNMANAGED 0x0800 /* No PV management for page */ diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 723b14d..d8cbdf0 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -111,7 +111,6 @@ __FBSDID("$FreeBSD$"); /* the kernel process "vm_pageout"*/ static void vm_pageout(void); -static int vm_pageout_clean(vm_page_t); static void vm_pageout_scan(int pass); struct proc *pageproc; @@ -274,7 +273,7 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next) * block. Note the careful timing, however, the busy bit isn't set till * late and we cannot do anything that will mess with the page. */ -static int +int vm_pageout_clean(m) vm_page_t m; { @@ -349,7 +348,7 @@ more: } vm_page_test_dirty(p); if (p->dirty == 0 || - p->queue != PQ_INACTIVE || + (p->queue != PQ_INACTIVE && p->queue != PQ_ACTIVE) || p->wire_count != 0 || /* may be held by buf cache */ p->hold_count != 0) { /* may be undergoing I/O */ ib = 0; @@ -377,7 +376,7 @@ more: } vm_page_test_dirty(p); if (p->dirty == 0 || - p->queue != PQ_INACTIVE || + (p->queue != PQ_INACTIVE && p->queue != PQ_ACTIVE) || p->wire_count != 0 || /* may be held by buf cache */ p->hold_count != 0) { /* may be undergoing I/O */ break; @@ -416,7 +415,7 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) vm_object_t object = mc[0]->object; int pageout_status[count]; int numpagedout = 0; - int i; + int i, wd_cleaned; mtx_assert(&vm_page_queue_mtx, MA_OWNED); VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); @@ -442,6 +441,7 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) vm_pager_put_pages(object, mc, count, flags, pageout_status); + wd_cleaned = 0; vm_page_lock_queues(); for (i = 0; i < count; i++) { vm_page_t mt = mc[i]; @@ -484,10 +484,18 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) if (pageout_status[i] != VM_PAGER_PEND) { vm_object_pip_wakeup(object); vm_page_io_finish(mt); - if (vm_page_count_severe()) + if (mt->queue == PQ_INACTIVE && vm_page_count_severe()) vm_page_try_to_cache(mt); + if ((mt->flags & PG_WRITEDIRTY) != 0 && + (pageout_status[i] == VM_PAGER_OK || + pageout_status[i] == VM_PAGER_BAD)) { + mt->flags &= ~PG_WRITEDIRTY; + wd_cleaned++; + } } } + if (wd_cleaned != 0) + vm_writedirty_cleaned(wd_cleaned); return numpagedout; } @@ -1180,7 +1188,6 @@ unlock_and_continue: vm_pageout_oom(VM_OOM_MEM); } - void vm_pageout_oom(int shortage) { @@ -1391,12 +1398,17 @@ vm_pageout() vm_pageout_page_count = 8; /* + * Try to allow not more then 1/4 of usable pages for write. + */ + vmio_max_writedirty = cnt.v_page_count / 4; + + /* * v_free_reserved needs to include enough for the largest * swap pager structures plus enough for any pv_entry structs * when paging. */ if (cnt.v_page_count > 1024) - cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200; + cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 100; else cnt.v_free_min = 4; cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE + diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index 15ca570..a2111be 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -77,6 +77,8 @@ extern int vm_pageout_pages_needed; extern int vm_pageout_deficit; extern int vm_pageout_page_count; +extern long vmio_max_writedirty; + /* * Swap out requests */ @@ -94,15 +96,18 @@ extern int vm_pageout_page_count; * Signal pageout-daemon and wait for it. */ +#ifdef _KERNEL extern void pagedaemon_wakeup(void); #define VM_WAIT vm_wait() #define VM_WAITPFAULT vm_waitpfault() extern void vm_wait(void); extern void vm_waitpfault(void); +extern void vm_wait_queue_free(const char *); -#ifdef _KERNEL boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *); int vm_pageout_flush(vm_page_t *, int, int); -void vm_pageout_oom(int shortage); +void vm_pageout_oom(int); +int vm_pageout_clean(vm_page_t); +void vm_writedirty_cleaned(int); #endif #endif /* _VM_VM_PAGEOUT_H_ */ diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c index a245462..393f741 100644 --- a/sys/vm/vm_phys.c +++ b/sys/vm/vm_phys.c @@ -778,4 +778,24 @@ DB_SHOW_COMMAND(freepages, db_show_freepages) db_printf("\n"); } } + +DB_SHOW_COMMAND(vpo_dw, vpo_dw) +{ + struct vm_phys_seg *seg; + vm_page_t m; + int segind; + long npages, i; + + for (segind = 0; segind < vm_phys_nsegs; segind++) { + seg = &vm_phys_segs[segind]; + npages = seg->end - seg->start; + npages /= PAGE_SIZE; + m = seg->first_page; + for (i = 0; i < npages; i++, m++) { + if (m->flags & PG_WRITEDIRTY) + printf("%p\n", m); + } + } +} + #endif diff --git a/sys/vm/vm_readwrite.c b/sys/vm/vm_readwrite.c new file mode 100644 index 0000000..234ec51 --- /dev/null +++ b/sys/vm/vm_readwrite.c @@ -0,0 +1,1081 @@ +/*- + * Copyright (c) 2008 Jeffrey Roberson + * Copyright (c) 2009 Konstantin Belousov + * 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 unmodified, 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. + * + * 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 +__FBSDID("$FreeBSD$"); + +#include "opt_vm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * XXXKIB TODO + * + * 2. VOP_REALLOCBLKS. + * 3. Unset setuid/setgid bits after write. + * 4. Filesystem full handling. + * + */ + +static SYSCTL_NODE(_vfs, OID_AUTO, vmio, CTLFLAG_RW, 0, "VFS VMIO leaf"); + +static int vmio_run = 0; +SYSCTL_INT(_vfs_vmio, OID_AUTO, run, CTLFLAG_RW, &vmio_run, 0, + "Calculate the max sequential run for vnode_pager_read_cluster"); +static int vmio_clrbuf = 1; +SYSCTL_INT(_vfs_vmio, OID_AUTO, clrbuf, CTLFLAG_RW, &vmio_clrbuf, 0, + ""); /* Intentionally undocumented */ +static int vmio_read_pack = 16; +SYSCTL_INT(_vfs_vmio, OID_AUTO, read_pack, CTLFLAG_RW, &vmio_read_pack, 0, + "Length of the page pack for read"); +static int vmio_write_pack = 16; +SYSCTL_INT(_vfs_vmio, OID_AUTO, write_pack, CTLFLAG_RW, &vmio_write_pack, + 0, + "Length of the page pack for write"); +static int vmio_rollbacks1; +SYSCTL_INT(_vfs_vmio, OID_AUTO, rollbacks1, CTLFLAG_RD, &vmio_rollbacks1, + 0, + "Count of times vnode size has to be rolled back for writes " + "while collecting pages"); +static int vmio_rollbacks2; +SYSCTL_INT(_vfs_vmio, OID_AUTO, rollbacks2, CTLFLAG_RD, &vmio_rollbacks2, + 0, + "Count of times vnode size has to be rolled back for writes " + "while reading pages"); +static int vmio_getpages_read; +SYSCTL_INT(_vfs_vmio, OID_AUTO, getpages_read, CTLFLAG_RD, + &vmio_getpages_read, 0, + "Count of times VOP_GETPAGES called for read"); +static int vmio_getpages_write; +SYSCTL_INT(_vfs_vmio, OID_AUTO, getpages_write, CTLFLAG_RD, + &vmio_getpages_write, 0, + "Count of times VOP_GETPAGES called for write"); +static int vmio_reserv_used; +SYSCTL_INT(_vfs_vmio, OID_AUTO, reserv_used, CTLFLAG_RD, + &vmio_reserv_used, 0, + "Count of times reserved page was used by vmio"); +static int vmio_alloc_wait; +SYSCTL_INT(_vfs_vmio, OID_AUTO, alloc_wait, CTLFLAG_RD, &vmio_alloc_wait, + 0, + "Count of times vmio reserved page allocation has to wait"); +static long vmio_writedirty; +SYSCTL_LONG(_vfs_vmio, OID_AUTO, writedirty, CTLFLAG_RD, &vmio_writedirty, + 0, + "Count of pages dirtied by vnode_pager_write"); +long vmio_max_writedirty; +SYSCTL_LONG(_vfs_vmio, OID_AUTO, max_writedirty, CTLFLAG_RW, + &vmio_max_writedirty, 0, + "Maximum allowed system-wide count of pages dirtied by vnode_pager_write"); +static int vmio_writed_wakeups; +SYSCTL_INT(_vfs_vmio, OID_AUTO, writed_wakeups, CTLFLAG_RD, + &vmio_writed_wakeups, 0, + "Count of times vmio write daemon was woken up"); +static int vmio_writed_inact; +SYSCTL_INT(_vfs_vmio, OID_AUTO, writed_inact, CTLFLAG_RD, + &vmio_writed_inact, 0, + "Count of times vmio write daemon cleaned inactive queue"); +static int vmio_writed_act; +SYSCTL_INT(_vfs_vmio, OID_AUTO, writed_act, CTLFLAG_RD, &vmio_writed_act, + 0, + "Count of times vmio write daemon cleaned active queue"); + +static u_int +io_page_bits(int i, vm_offset_t off, ssize_t size) +{ + int start, chunk; + + if (i == 0) { + start = off; + chunk = min(PAGE_SIZE - off, size); + } else if (i * PAGE_SIZE < off + size) { + start = 0; + chunk = PAGE_SIZE; + } else if ((i - 1) * PAGE_SIZE < off + size) { + start = 0; + chunk = (size - off) % PAGE_SIZE; + } else + return (0); + return (vm_page_bits(start, chunk)); +} + +/* + * Blocking allocator of the reserve page. Cannot be called with vnode + * or object lock held. + */ +static void +vnode_alloc_reserv(vm_page_t *reserv) +{ + + if (*reserv != NULL) + return; + while (*reserv == NULL) { + *reserv = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ); + if (*reserv == NULL) { + atomic_add_int(&vmio_alloc_wait, 1); + VM_WAIT; + } + } +} + +/* + * Copied from vm_pageout_scan(). + */ +static int +vnode_writedirty_clean_page(vm_page_t m, int queue, int *target, + vm_page_t *next) +{ + vm_object_t object; + struct mount *mp; + struct vnode *vp; + struct vm_page marker; + int vfslocked, actcount; + + bzero(&marker, sizeof(marker)); + marker.flags = PG_FICTITIOUS | PG_MARKER; + marker.oflags = VPO_BUSY; + marker.queue = queue; + marker.wire_count = 1; + + if (VM_PAGE_GETQUEUE(m) != queue) + return (0); + *next = TAILQ_NEXT(m, pageq); + object = m->object; + + if (m->flags & PG_MARKER) + return (1); + if (m->hold_count) { + vm_page_requeue(m); + return (1); + } + if (!VM_OBJECT_TRYLOCK(object) && + (!vm_pageout_fallback_object_lock(m, next) || + m->hold_count != 0)) { + VM_OBJECT_UNLOCK(object); + return (1); + } + if (m->busy || (m->oflags & VPO_BUSY) || !(m->flags & PG_WRITEDIRTY)) { + VM_OBJECT_UNLOCK(object); + return (1); + } + if (object->ref_count == 0) { + vm_page_flag_clear(m, PG_REFERENCED); + KASSERT(!pmap_page_is_mapped(m), + ("vm_pageout_clean_writedirty: page %p is mapped", m)); + } else if (((m->flags & PG_REFERENCED) == 0) && + (actcount = pmap_ts_referenced(m))) { + vm_page_activate(m); + VM_OBJECT_UNLOCK(object); + m->act_count += (actcount + ACT_ADVANCE); + return (1); + } + + if ((m->flags & PG_REFERENCED) != 0) { + vm_page_flag_clear(m, PG_REFERENCED); + actcount = pmap_ts_referenced(m); + vm_page_activate(m); + VM_OBJECT_UNLOCK(object); + m->act_count += (actcount + ACT_ADVANCE + 1); + return (1); + } + + if (m->dirty != VM_PAGE_BITS_ALL && (m->flags & PG_WRITEABLE) != 0) { + if (pmap_is_modified(m)) + vm_page_dirty(m); + else if (m->dirty == 0) + pmap_remove_all(m); + } + + KASSERT(m->valid != 0, ("VPO_WRITEDIRTY and not valid %p", m)); + if (m->dirty == 0) { + m->flags &= ~PG_WRITEDIRTY; + vmio_writedirty--; + VM_OBJECT_UNLOCK(object); + return (1); + } + KASSERT(m->dirty != 0, ("VPO_WRITEDIRTY and not dirty %p", m)); + if (object->flags & OBJ_DEAD) { + VM_OBJECT_UNLOCK(object); + vm_page_requeue(m); + return (1); + } + KASSERT(object->type == OBJT_VNODE, ("VPO_WRITEDIRTY and not vnode")); + + TAILQ_INSERT_AFTER(&vm_page_queues[queue].pl, m, &marker, pageq); + vp = object->handle; + vfslocked = 0; + if (vp->v_type == VREG && vn_start_write(vp, &mp, V_NOWAIT) != 0) { + mp = NULL; + goto unlock_and_continue; + } + KASSERT(mp != NULL, ("vp %p with NULL v_mount", vp)); + vm_page_unlock_queues(); + vm_object_reference_locked(object); + VM_OBJECT_UNLOCK(object); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + if (vget(vp, LK_EXCLUSIVE | LK_TIMELOCK, curthread)) { + VM_OBJECT_LOCK(object); + vm_page_lock_queues(); + vp = NULL; + goto unlock_and_continue; + } + VM_OBJECT_LOCK(object); + vm_page_lock_queues(); + if (VM_PAGE_GETQUEUE(m) != queue || m->object != object || + TAILQ_NEXT(m, pageq) != &marker) + goto unlock_and_continue; + if (m->busy || (m->oflags & VPO_BUSY)) + goto unlock_and_continue; + if (m->hold_count) { + vm_page_requeue(m); + goto unlock_and_continue; + } + if (vm_pageout_clean(m) != 0) + (*target)--; + unlock_and_continue: + VM_OBJECT_UNLOCK(object); + if (mp != NULL) { + vm_page_unlock_queues(); + if (vp != NULL) + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); + vm_object_deallocate(object); + vn_finished_write(mp); + vm_page_lock_queues(); + } + *next = TAILQ_NEXT(&marker, pageq); + TAILQ_REMOVE(&vm_page_queues[queue].pl, &marker, pageq); + return (1); +} + +static void +vnode_writedirty_clean_queue(int *target, int queue) +{ + vm_page_t m, next; + + vm_page_lock_queues(); + rescan0: + for (m = TAILQ_FIRST(&vm_page_queues[queue].pl); + m != NULL && *target > 0; m = next) { + if (!vnode_writedirty_clean_page(m, queue, target, &next)) + goto rescan0; + } + vm_page_unlock_queues(); +} + +static struct cv wd_speedup; +static struct cv wd_back; + +static void +vnode_writedirty_daemon(void) +{ + int target; + + cv_init(&wd_speedup, "writed"); + cv_init(&wd_back, "vnodeww"); + + vm_page_lock_queues(); + for (;;) { + cv_wait(&wd_speedup, &vm_page_queue_mtx); + target = vmio_writedirty - vmio_max_writedirty; + vm_page_unlock_queues(); + atomic_add_int(&vmio_writed_wakeups, 1); + if (target > 0) { + if (target > 0) { + bwillwrite(); + atomic_add_int(&vmio_writed_inact, 1); + vnode_writedirty_clean_queue(&target, + PQ_INACTIVE); + } + if (target > 0) { + bwillwrite(); + atomic_add_int(&vmio_writed_act, 1); + vnode_writedirty_clean_queue(&target, + PQ_ACTIVE); + } + } + vm_page_lock_queues(); + vm_writedirty_cleaned(0); + } +} + +void +vm_writedirty_cleaned(int cnt) +{ + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vmio_writedirty -= cnt; + cv_broadcast(&wd_back); +} + +static struct proc *writedproc; +static struct kproc_desc writed_kp = { + .arg0 = "writed", + .func = vnode_writedirty_daemon, + .global_procpp = &writedproc +}; +SYSINIT(writed, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY, kproc_start, &writed_kp); + +/* + * Attempt to put backpressure on writes. + */ +static void +vnode_pager_wwait(void) +{ + + if (vmio_writedirty >= vmio_max_writedirty) { + vm_page_lock_queues(); + while (vmio_writedirty >= vmio_max_writedirty) { + cv_signal(&wd_speedup); + cv_wait(&wd_back, &vm_page_queue_mtx); + } + vm_page_unlock_queues(); + } +} + +#define VN_GRAB_NO_VMWAIT 0x0001 + +/* + * Grab a page, waiting until we are woken up due to the page + * changing state. We keep on waiting, if the page continues + * to be in the object. If the page doesn't exist allocate it. + * + * This routine may block, either waiting for busy vnode page, or for + * a page allocation. Later may be disabled with VN_GRAB_NO_VMWAIT + * flag, when vnode lock is held. To ensure progress, reserve page is + * used for ma[0] when wait is disabled and system cannot provide a + * page. + * + * Returns updated page run length in *wp, and filled in ma page + * array. + */ +static void +vnode_grab_pages(struct vnode *vp, vm_page_t *ma, int *wp, vm_pindex_t pindex, + int flags, vm_page_t *reserv) +{ + vm_object_t object; + vm_page_t m; + vm_pindex_t pi; + int i; + + KASSERT((flags & VN_GRAB_NO_VMWAIT) || reserv == NULL, + ("vnode_grab_pages: NO_VMWAIT and no reserve")); + + object = vp->v_object; + redo: + VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); + m = NULL; + for (i = 0, pi = pindex; i < *wp; ) { + if (i > 0) { + m = TAILQ_NEXT(ma[i - 1], listq); + if (m && m->pindex != pi) + m = NULL; + } + if (m == NULL) + m = vm_page_lookup(object, pi); + if (m != NULL) { + if (vm_page_sleep_if_busy(m, TRUE, "pgrnbwt")) + goto redo; + } else { + m = vm_page_alloc(object, pi, VM_ALLOC_NORMAL | + VM_ALLOC_NOBUSY); + } + if (m != NULL) { + ma[i] = m; + i++; + pi++; + continue; + } + if (flags & VN_GRAB_NO_VMWAIT) { + if (i == 0) { + m = *reserv; + *reserv = NULL; + atomic_add_int(&vmio_reserv_used, 1); + if (object->memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, + object->memattr); + vm_page_insert(m, object, pindex); + vm_page_lock_queues(); + vm_page_flag_clear(m, PG_UNMANAGED); + vm_page_unlock_queues(); + ma[i] = m; + i++; + } + break; + } + VM_OBJECT_UNLOCK(object); + atomic_add_int(&vmio_alloc_wait, 1); + VM_WAIT; + VM_OBJECT_LOCK(object); + goto redo; + } + *wp = i; +} + +/* + * Read a cluster starting at 'ma'. Note that we need to always redo + * page grab because our caller dropped object lock while not holding + * vnode lock. + */ +static int +vnode_pager_read_cluster(struct vnode *vp, vm_page_t ma[], vm_pindex_t idx, + int *maxrun, int flags, vm_page_t *reserv) +{ + vm_object_t obj; + vm_page_t m; + daddr_t blkno; + int bsize; + int error; + int run; + int i; + + obj = vp->v_object; + bsize = vp->v_mount->mnt_stat.f_iosize; + error = 0; + blkno = 0; + + if (vmio_run) { + VM_OBJECT_UNLOCK(obj); + error = VOP_BMAP(vp, IDX_TO_OFF(idx)/bsize, NULL, &blkno, &run, + NULL); + VM_OBJECT_LOCK(obj); + run = MIN(run, *maxrun); + if (error || run == 0 || blkno == -1) { +/* printf("vnode_pager_read_cluster short\n"); */ + *maxrun = 1; + vnode_grab_pages(vp, ma, maxrun, idx, + VN_GRAB_NO_VMWAIT, reserv); + error = vm_pager_get_pages(obj, ma, 1, 0); + if (error != VM_PAGER_OK) + return (EIO); + return (0); + } + run = (run + 1) * bsize / PAGE_SIZE; + run = MIN(run, vp->v_mount->mnt_iosize_max / PAGE_SIZE); + } else { + if (*maxrun == 0) + *maxrun = 1; + run = MIN(*maxrun, vp->v_mount->mnt_iosize_max / PAGE_SIZE); + } + if (IDX_TO_OFF(idx) + run * PAGE_SIZE > obj->un_pager.vnp.vnp_size) { + run = (obj->un_pager.vnp.vnp_size - IDX_TO_OFF(idx)) / + PAGE_SIZE; + } + if (run == 0) + run = 1; + vnode_grab_pages(vp, ma, &run, idx, VN_GRAB_NO_VMWAIT, reserv); + for (i = 0; i < run; i++) { + if (i > 0 && ma[i]->valid != 0) { + run = i; + break; + } + vm_page_busy(ma[i]); + } + +/* printf("vnode_pager_read_cluster %d %p %p\n", run, ma, ma[0]); */ + error = vm_pager_get_pages(obj, ma, run, 0); + if (error != VM_PAGER_OK) { + vm_page_lock_queues(); + for (i = 0; i < run; i++) + vm_page_free(ma[i]); + vm_page_unlock_queues(); + return (EIO); + } + KASSERT(ma[0]->valid == VM_PAGE_BITS_ALL, + ("ma[0]->valid %x", ma[0]->valid)); + vm_page_wakeup(ma[0]); + /* ma[0] cannot be cached */ + for (i = 1; i < run; i++) { + m = TAILQ_NEXT(ma[i - 1], listq); + if (m == NULL || m->pindex != ma[0]->pindex + i || + ma[i] != m || m->valid == 0) + break; + ma[i] = m; +/* printf("run %d ma[%d]: obj %p %p pindex %jd p+i %jd valid %x\n", + run, i, obj, ma[i]->object, ma[i]->pindex, ma[0]->pindex + i, ma[i]->valid); */ + } + *maxrun = i; + return (0); +} + +int +vnode_pager_read(struct vnode *vp, struct uio *uio, int ioflags) +{ + vm_object_t obj; + vm_offset_t off; + vm_pindex_t idx; + vm_page_t reserv; + ssize_t size; + int error, seqcount, wpmax, wp, i; + u_int bits; + struct thread *td; + + if (ioflags & (IO_EXT|IO_DIRECT)) + return (EOPNOTSUPP); + + ASSERT_VOP_LOCKED(vp, "vnode_pager_read"); + if (vp->v_iflag & VI_DOOMED) + return (EBADF); + + /* + * Ignore non-regular files. + */ + if (vp->v_type != VREG) + return (EOPNOTSUPP); + obj = vp->v_object; + if (obj == NULL) + return (EOPNOTSUPP); + + seqcount = (ioflags >> IO_SEQSHIFT) * FRA_BLOCK_SZ / PAGE_SIZE; + seqcount = min(vfs_read_max, seqcount); + seqcount = min(vp->v_mount->mnt_iosize_max / PAGE_SIZE, seqcount); + VOP_UNLOCK(vp, 0); + + wpmax = atomic_load_acq_int(&vmio_read_pack); + vm_page_t ma[wpmax + 1]; + + while (vm_page_count_severe()) { + atomic_add_int(&vm_pageout_deficit, MIN(wpmax + 1, + (uio->uio_resid + PAGE_SIZE - 1) >> PAGE_SHIFT)); + VM_WAIT; + } + + error = 0; + reserv = NULL; + td = uio->uio_td; + /* XXXKIB This should be disallowed. */ + if (td == NULL) + td = curthread; + + VM_OBJECT_LOCK(obj); + while (uio->uio_resid > 0) { + wp = wpmax; + + size = obj->un_pager.vnp.vnp_size - uio->uio_offset; + if (size <= 0) + break; + idx = OFF_TO_IDX(uio->uio_offset); + off = uio->uio_offset - IDX_TO_OFF(idx); + size = MIN(MIN(PAGE_SIZE * wp - off, uio->uio_resid), size); + + wp = (size + off + PAGE_SIZE - 1) / PAGE_SIZE; + vnode_grab_pages(vp, ma, &wp, idx, 0, NULL); + find_valid: + for (i = 0; i < wp; i++) { + bits = io_page_bits(i, off, size); + + /* + * Only do read if first page of array is not + * valid for us. We have to drop object lock + * to obtain vnode lock, that allows the pages + * to change identity or validity bits, and we + * can guarantee allocation of only one + * (reserved) page. + */ + if ((ma[i]->valid & bits) != bits) { + if (i != 0) { + wp = i; + break; + } + VM_OBJECT_UNLOCK(obj); + vnode_alloc_reserv(&reserv); + error = vn_lock(vp, LK_SHARED); + VM_OBJECT_LOCK(obj); + if (error != 0) { + error = EBADF; + break; + } + + /* + * Read page, honouring read-ahead settings + * for filedescriptor. + */ + atomic_add_int(&vmio_getpages_read, 1); + error = vnode_pager_read_cluster(vp, ma, idx, + &wp, VN_GRAB_NO_VMWAIT, &reserv); + VOP_UNLOCK(vp, 0); + if (error != 0) + break; + /* + * No need to redo size calculation. + * Despite both vnode and object locks + * were dropped, range lock and file + * descriptor reference shall keep + * file from truncation. + */ + goto find_valid; + } + } + if (error != 0) + break; + KASSERT(wp > 0, ("wp == 0")); +/* printf("vp %p wp %d size %d\n", vp, wp, size); */ + + /* + * Prevent object deallocation and pages swap-out. + */ + vm_object_pip_add(obj, 1); + vm_page_lock_queues(); + for (i = 0; i < wp; i++) + vm_page_hold(ma[i]); + vm_page_unlock_queues(); + VM_OBJECT_UNLOCK(obj); + + /* + * Recalculate i/o size, since vnode_grab_pages() + * might shortened the page run. + */ + size = MIN(MIN(PAGE_SIZE * wp - off, uio->uio_resid), size); + + /* + * Access user map pages, vnode lock is dropped. + * Possible page fault is safe at this point. Vnode + * rangelock is held, protecting from parallel + * writers. + */ +/* printf("size %d %d %ju\n", size, uio->uio_resid, (uintmax_t)off); */ + KASSERT((td->td_pflags & TDP_VMIO) == 0, + ("Recursed vnode_pager_read")); + td->td_pflags |= TDP_VMIO; + error = uiomove_fromphys(ma, off, size, uio); + td->td_pflags &= ~TDP_VMIO; + + VM_OBJECT_LOCK(obj); + vm_page_lock_queues(); + for (i = 0; i < wp; i++) { + vm_page_unhold(ma[i]); + vm_page_activate(ma[i]); + } + vm_page_unlock_queues(); + vm_object_pip_wakeup(obj); + if (error != 0) + break; + } + VM_OBJECT_UNLOCK(obj); + if (reserv != NULL) + vm_page_free(reserv); + vn_lock(vp, LK_SHARED | LK_RETRY); + if (error == 0) + vfs_mark_atime(vp, td->td_ucred); + + return (error); +} + +int +vnode_pager_write(struct vnode *vp, struct uio *uio, int ioflags) +{ + vm_object_t obj; + vm_offset_t off; + vm_pindex_t idx, clean_start, clean_end; + vm_page_t reserv; + struct vattr vattr; + ssize_t size, size1, osize, osize1, resid, sresid; + int error, vn_locked, wpmax, wp, i; + u_int bits; + boolean_t vnode_locked; + struct thread *td; + + if (ioflags & (IO_EXT|IO_INVAL|IO_DIRECT)) + return (EOPNOTSUPP); + ASSERT_VOP_LOCKED(vp, "vnode_pager_write"); + if (vp->v_iflag & VI_DOOMED) + return (EBADF); + if (vp->v_type != VREG) + return (EOPNOTSUPP); + obj = vp->v_object; + if (obj == NULL) + return (EOPNOTSUPP); + vn_locked = VOP_ISLOCKED(vp); + vnode_locked = TRUE; + error = 0; + + wpmax = atomic_load_acq_int(&vmio_write_pack); + vm_page_t ma[wpmax + 1]; + + /* + * Try to ensure that enough pages is available in advance. + */ + while (vm_page_count_severe()) { + if (vnode_locked) { + VOP_UNLOCK(vp, 0); + vnode_locked = FALSE; + } + atomic_add_int(&vm_pageout_deficit, MIN(wpmax + 1, + (uio->uio_resid + PAGE_SIZE - 1) >> PAGE_SHIFT)); + VM_WAIT; + } + + /* + * Allocate first reserve page. + */ + for (reserv = NULL; reserv == NULL; ) { + reserv = vm_page_alloc(NULL, 0, + VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ); + if (reserv == NULL) { + if (vnode_locked) { + VOP_UNLOCK(vp, 0); + vnode_locked = FALSE; + } + atomic_add_int(&vmio_alloc_wait, 1); + VM_WAIT; + } + } + if (!vnode_locked) { + /* + * Since vnode lock was dropped, we are under low free + * pages condition, so more write trottling is due. + */ + vnode_pager_wwait(); + + vn_lock(vp, vn_locked | LK_RETRY); + if (vp->v_iflag & VI_DOOMED) { + if (reserv != NULL) + vm_page_free(reserv); + return (EBADF); + } + vnode_locked = TRUE; + } + + if (ioflags & IO_APPEND) + uio->uio_offset = obj->un_pager.vnp.vnp_size; + + clean_start = OFF_TO_IDX(uio->uio_offset); + clean_end = OFF_TO_IDX(uio->uio_offset + uio->uio_resid + + PAGE_SIZE - 1); + + td = uio->uio_td; + if (td == NULL) + td = curthread; + + /* + * Enforce the RLIMIT_FSIZE there too. + * XXXKIB the check for the file type is kept on purpose. + */ + if (vp->v_type == VREG) { + PROC_LOCK(td->td_proc); + if (uio->uio_offset + uio->uio_resid > + lim_cur(td->td_proc, RLIMIT_FSIZE)) { + psignal(td->td_proc, SIGXFSZ); + PROC_UNLOCK(td->td_proc); + return (EFBIG); + } + PROC_UNLOCK(td->td_proc); + } + osize = osize1 = obj->un_pager.vnp.vnp_size; + resid = uio->uio_resid; + + io_loop: + while (uio->uio_resid > 0) { + wp = wpmax; + size = uio->uio_resid; + idx = OFF_TO_IDX(uio->uio_offset); + off = uio->uio_offset - IDX_TO_OFF(idx); + size = MIN(PAGE_SIZE * wp - off, uio->uio_resid); + if (!vnode_locked) { + error = vn_lock(vp, LK_EXCLUSIVE); + if (error != 0) { + error = EBADF; + break; + } + vnode_locked = TRUE; + } + osize1 = obj->un_pager.vnp.vnp_size; + + /* + * Extend the file if writing past end. + */ + if (osize1 < uio->uio_offset + size) { + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + VOP_UNLOCK(vp, 0); + vnode_locked = FALSE; + } + if (!vnode_locked) { + error = vn_lock(vp, LK_EXCLUSIVE); + if (error != 0) { + error = EBADF; + break; + } + vnode_locked = TRUE; + } + vattr.va_size = uio->uio_offset + size; + error = VOP_EXTEND(vp, td->td_ucred, uio->uio_offset + + size, ioflags); + } + if (error != 0) + break; + + wp = (size + off + PAGE_SIZE - 1) / PAGE_SIZE; + VM_OBJECT_LOCK(obj); + + /* + * Use VN_GRAB_NO_VMWAIT since vnode lock is held. + */ + vnode_grab_pages(vp, ma, &wp, idx, VN_GRAB_NO_VMWAIT, &reserv); + find_valid: + for (i = 0; i < wp; i++) { + /* + * If the page falls into the newly-extended + * range, zero it and mark as valid. There is + * nothing VOP_GETPAGES can read from file. + */ + if (IDX_TO_OFF(ma[i]->pindex) >= osize1) { + if ((ma[i]->flags & PG_ZERO) == 0) + pmap_zero_page(ma[i]); + ma[i]->valid = VM_PAGE_BITS_ALL; + } + + /* + * Pages need to be fully valid, because we + * can only hold them during uiomove later. + * + * The page fault happening in other thread + * after uiomove finished but before valid + * bits are corrected below would cause lost + * of newly written data if page is not fully + * valid. + */ + if (ma[i]->valid == VM_PAGE_BITS_ALL) + continue; + if (!vmio_clrbuf) { + bits = io_page_bits(i, off, size); + if ((ma[i]->valid & ~bits) == (~bits & + VM_PAGE_BITS_ALL)) + continue; + } + if (i != 0) { + wp = i; + break; + } + if (reserv == NULL) + reserv = vm_page_alloc(NULL, 0, + VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ); + if (reserv == NULL) { + VM_OBJECT_UNLOCK(obj); + + /* + * Truncate the file back to the + * original size to prevent mmap from + * seeing invalid pages. We are going + * to drop vnode lock. + */ + if (osize1 < uio->uio_offset + size) { + atomic_add_int(&vmio_rollbacks1, 1); + VATTR_NULL(&vattr); + vattr.va_size = osize1; + error = VOP_SETATTR(vp, &vattr, + td->td_ucred); + if (error != 0) + break; + } + KASSERT(vnode_locked, ("lost vnode lock 1")); + VOP_UNLOCK(vp, 0); + vnode_locked = FALSE; + vnode_pager_wwait(); + vnode_alloc_reserv(&reserv); + goto io_loop; + } + + atomic_add_int(&vmio_getpages_write, 1); + error = vnode_pager_read_cluster(vp, ma, idx, &wp, + VN_GRAB_NO_VMWAIT, &reserv); + if (error != 0) { + VM_OBJECT_UNLOCK(obj); + break; + } + goto find_valid; + } + /* Loop above is exited with unlocked obj if error != 0. */ + if (error != 0) + break; + KASSERT(wp > 0, ("wp == 0")); + + /* + * Prevent the object deallocation and hold the pages. + * Held page can be removed from object, but cannot be + * reused. Range lock taken in vn_truncate() prevents + * most typical race. + * + * XXXKIB Busying the pages there would cause deadlock + * with vm_object_page_remove() or self-lock with + * vm_fault(), but would allow to not require the + * pages to be fully valid before uiomove. + * + * The mmap could see zeroed pages that are inserted + * into extended area after we dropped object lock. + * This could be considered an application race. + */ + vm_object_pip_add(obj, 1); + vm_page_lock_queues(); + for (i = 0; i < wp; i++) + vm_page_hold(ma[i]); + vm_page_unlock_queues(); + VM_OBJECT_UNLOCK(obj); + + /* + * Recalculate i/o size, since vnode_grab_pages() + * might have shortened the page run. Save previous + * resid to correctly mark written pages regions as + * dirty. + */ + sresid = uio->uio_resid; + size1 = MIN(MIN(PAGE_SIZE * wp - off, sresid), size); + + /* + * Shrunk file in case we allocated less pages then + * the estimation that was used to VOP_EXTEND. + */ + KASSERT(vnode_locked, ("lost vnode lock 2")); + if (size1 < size && osize1 < uio->uio_offset + size) { + atomic_add_int(&vmio_rollbacks2, 1); + VATTR_NULL(&vattr); + vattr.va_size = uio->uio_offset + size1; + error = VOP_SETATTR(vp, &vattr, td->td_ucred); + if (error != 0) { + VM_OBJECT_LOCK(obj); + vm_page_lock_queues(); + for (i = 0; i < wp; i++) { + vm_page_unhold(ma[i]); + vm_page_deactivate(ma[i]); + } + vm_page_unlock_queues(); + vm_object_pip_wakeup(obj); + VM_OBJECT_UNLOCK(obj); + break; + } + } + size = size1; + + VOP_UNLOCK(vp, 0); + vnode_locked = FALSE; + + KASSERT((td->td_pflags & TDP_VMIO) == 0, + ("Recursed vnode_pager_write")); +/* printf("W: vp %p off %jd %jd size %jd\n", + vp, (intmax_t)uio->uio_offset, (intmax_t)off, (intmax_t)size); */ + td->td_pflags |= TDP_VMIO; + error = uiomove_fromphys(ma, off, size, uio); + td->td_pflags &= ~TDP_VMIO; + + VM_OBJECT_LOCK(obj); + vm_page_lock_queues(); + for (i = 0; i < wp; i++) { + /* + * Note that the page is dirty regardeless of + * the possible error from uiomove. We must + * mark the pages that were touched by uiomove + * before fault occured. Since we do not + * record the progress of the uiomove till + * fault, just mark them all. + */ + ma[i]->dirty |= io_page_bits(i, off, sresid - + uio->uio_resid); + if ((ma[i]->flags & PG_WRITEDIRTY) == 0) { + ma[i]->flags |= PG_WRITEDIRTY; + vmio_writedirty++; + } + vm_page_unhold(ma[i]); + vm_page_activate(ma[i]); + } + vm_page_unlock_queues(); + /* See the comment above about page dirtiness. */ + vm_object_set_writeable_dirty(obj); + vm_object_pip_wakeup(obj); + VM_OBJECT_UNLOCK(obj); + if (error != 0) + break; + KASSERT(!vnode_locked, ("vnode leak 3")); + + vnode_pager_wwait(); + + /* + * Re-fill reserv while vnode lock is dropped. + */ + if (uio->uio_resid != 0) + vnode_alloc_reserv(&reserv); + } + + if (!vnode_locked) + vn_lock(vp, vn_locked | LK_RETRY); + if (reserv != NULL) + vm_page_free(reserv); + if (vp->v_iflag & VI_DOOMED) { + if (error == 0) + error = EBADF; + return (error); + } + if (error == 0) { + if (((ioflags & IO_SYNC) && (vp->v_vflag & VV_NOSYNC)) || + vm_page_count_severe()) { + VM_OBJECT_LOCK(obj); + vm_object_page_clean(obj, clean_start, clean_end, + OBJPC_SYNC); + VM_OBJECT_UNLOCK(obj); +#if 0 + /* + * XXXKIB The following call is commented out in + * vm_object_page_clean() in the same way. + */ + error = VOP_FSYNC(vp, MNT_WAIT, td); +#endif + } + } else { + /* + * Roll back on error if atomic write was requested. + */ + VATTR_NULL(&vattr); + vattr.va_size = (ioflags & IO_UNIT) ? osize : osize1; + VOP_SETATTR(vp, &vattr, td->td_ucred); + if (ioflags & IO_UNIT) { + uio->uio_offset -= resid - uio->uio_resid; + uio->uio_resid = resid; + } + } + + return (error); +} diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 179afbf..37fbe64 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -697,6 +697,7 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) object = vp->v_object; count = bytecount / PAGE_SIZE; +/* printf("vpgg: %p %jd %x %d\n", vp, m[0]->pindex, count, reqpage); */ KASSERT(vp->v_type != VCHR && vp->v_type != VBLK, ("vnode_pager_generic_getpages does not support devices")); @@ -1081,6 +1082,7 @@ vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals) object = vp->v_object; count = bytecount / PAGE_SIZE; +/* printf("vpgp: %p %jd %x %d\n", vp, m[0]->pindex, m[0]->dirty, count); */ for (i = 0; i < count; i++) rtvals[i] = VM_PAGER_AGAIN; diff --git a/tools/regression/file/uio/uio.c b/tools/regression/file/uio/uio.c new file mode 100644 index 0000000..d857605 --- /dev/null +++ b/tools/regression/file/uio/uio.c @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2009 Konstantin Belousov + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int chunk_cnt = 1024; +int chunk_size = 1024; + +int +main(int argc, char *argv[]) +{ + struct iovec *wiov, *riov; + char **wdata, **rdata; + int fd, i; + ssize_t io_error; + + if (argc < 2) { + fprintf(stderr, "Usage: uio file [chunk count [chunk size]]\n"); + return (2); + } + fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) { + fprintf(stderr, "Failed to create %s: %s\n", + argv[1], strerror(errno)); + return (1); + } + + if (argc > 2) + chunk_cnt = atoi(argv[2]); + if (argc > 3) + chunk_size = atoi(argv[3]); + + wiov = calloc(chunk_cnt, sizeof(*wiov)); + wdata = calloc(chunk_cnt, sizeof(*wdata)); + + riov = calloc(chunk_cnt, sizeof(*riov)); + rdata = calloc(chunk_cnt, sizeof(*rdata)); + + for (i = 0; i < chunk_cnt; i++) { + rdata[i] = malloc(chunk_size); + riov[i].iov_base = rdata[i]; + riov[i].iov_len = chunk_size; + + wdata[i] = malloc(chunk_size); + memset(wdata[i], i, chunk_size); + wiov[i].iov_base = wdata[i]; + wiov[i].iov_len = chunk_size; + } + + io_error = writev(fd, wiov, chunk_cnt); + if (io_error == -1) { + fprintf(stderr, "write failed: %s\n", strerror(errno)); + return (1); + } else if (io_error != chunk_cnt * chunk_size) { + fprintf(stderr, "truncated write: %d %d\n", + io_error, chunk_cnt * chunk_size); + return (1); + } + + if (lseek(fd, 0, SEEK_SET) == -1) { + fprintf(stderr, "lseek failed: %s\n", strerror(errno)); + return (1); + } + + io_error = readv(fd, riov, chunk_cnt); + if (io_error == -1) { + fprintf(stderr, "read failed: %s\n", strerror(errno)); + return (1); + } else if (io_error != chunk_cnt * chunk_size) { + fprintf(stderr, "truncated read: %d %d\n", + io_error, chunk_cnt * chunk_size); + return (1); + } + + for (i = 0; i < chunk_cnt; i++) { + if (memcmp(rdata[i], wdata[i], chunk_size) != 0) { + fprintf(stderr, "chunk %d differs\n", i); + return (1); + } + } + + return (0); +} diff --git a/tools/regression/ufs/ba_clrbuf/ba_clrbuf.c b/tools/regression/ufs/ba_clrbuf/ba_clrbuf.c new file mode 100644 index 0000000..1b0acbe --- /dev/null +++ b/tools/regression/ufs/ba_clrbuf/ba_clrbuf.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2009 Konstantin Belousov + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int blks = 2; + +static void +flush_buffers(int fd) +{ + struct stat st; + char *addr; + int error; + + printf("Flushing buffers\n"); + error = fstat(fd, &st); + if (error == -1) + err(2, "stat"); + fsync(fd); + addr = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == (char *)-1) + err(2, "mmap"); + error = msync(addr, st.st_size, MS_SYNC | MS_INVALIDATE); + if (error == -1) + err(2, "msync"); + munmap(addr, st.st_size); +} + +int +main(int argc, char *argv[]) +{ + struct statfs fst; + char *data, *vrfy; + size_t sz; + int fd, i, error, ret; + + if (argc < 2) + errx(2, "Usage: ba_clrbuf file"); + + fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) + err(2, "Failed to create %s", argv[1]); + + if (fstatfs(fd, &fst) == -1) + err(2, "stat"); + + sz = fst.f_iosize * blks; + data = malloc(sz); + if (data == NULL) + err(2, "malloc"); + vrfy = malloc(sz); + if (vrfy == NULL) + err(2, "malloc"); + for (i = 0; i < (int)sz; i++) + data[i] = i; + error = write(fd, data, sz); + if (error == -1) + err(2, "write"); + else if (error != (int)sz) + errx(2, "Short write %d %d", error, sz); + + flush_buffers(fd); + + error = lseek(fd, 0, SEEK_SET); + if (error == -1) + err(2, "lseek 0"); + else if (error != 0) + errx(2, "lseek 0 returned %d", error); + error = write(fd, NULL, fst.f_iosize); + printf("faulty write, error %s\n", strerror(errno)); + + error = lseek(fd, 0, SEEK_SET); + if (error == -1) + err(2, "lseek 0/2"); + else if (error != 0) + errx(2, "lseek 0/2 returned %d", error); + error = read(fd, vrfy, sz); + if (error == -1) + err(2, "read"); + else if (error != (int)sz) + errx(2, "short read %d %d", error, sz); + + if (memcmp(data, vrfy, fst.f_iosize) != 0) { + printf("Zero block corrupted, byte at 0 is %x\n", + (unsigned char)vrfy[0]); + ret = 1; + } else { + printf("No corruption\n"); + ret = 0; + } + + return (ret); +}