Subject: kern/11813: uvm_fault() can spin forever ubc_fault()-ing
To: None <gnats-bugs@gnats.netbsd.org>
From: John Hawkinson <jhawk@mit.edu>
List: netbsd-bugs
Date: 12/25/2000 00:24:16
>Number:         11813
>Category:       kern
>Synopsis:       uvm_fault() can spin forever ubc_fault()-ing
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Dec 25 00:24:00 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     John Hawkinson
>Release:        -current of 24 Dec 2000
>Organization:
MIT
>Environment:
	
System: NetBSD zorkmid.mit.edu 1.5O NetBSD 1.5O (ZORKMID-$Revision: 1.5 $) #67: Sat Dec 23 17:45:30 EST 2000 jhawk@zorkmid.mit.edu:/usr/local/netbsd-current/src/sys/arch/i386/compile/ZORKMID i386


>Description:
	ubc_fault() calls VOP_GETPAGES(). VOP_GETPAGES() returns an errno
value. ubc_fault() treats it as a a VM_PAGER_FOOBAR value. THese are not
compatible strategies.

	This results in VOP_PAGER_REFAULT if E2BIG is returned, which
means we spin forever rereading the same block. This causes a LOT of
disk activity, and is pretty unpleasant, and it's not possible to
interrupt the process without kernel hackery.

	Thanks very much to mycroft for helping me debug this at 3am
on christmas morning.

>How-To-Repeat:
	Do something with msdosfs. I tried grep-ing though a directory,
but I also saw it while running COMPAT_PECOFF stuff from msdosfs.




ASIDE:
	Useful tip of the day when working with someone who can't
see the console, and you're typing on it and you have no serial console:
patch ddb so that db_printf() sends messages to the message buffer as
well as the console. Since db_printf() is basically just:

        kprintf(fmt, TODDB, NULL, NULL, ap);

and we know:

/* flags for kprintf */
#define TOCONS          0x01    /* to the console */
#define TOTTY           0x02    /* to the process' tty */
#define TOLOG           0x04    /* to the kernel message buffer */
#define TOBUFONLY       0x08    /* to the buffer (only) [for sprintf] */
#define TODDB           0x10    /* to ddb console */


so we'd like it to be TODDB|TOLOG, so 0x14 instead of 0x10.

db> x/i db_printf,9
db> db_printf:  pushl   %ebp
db_printf+0x1:  movl    %esp,%ebp
db_printf+0x3:  leal           0xc(%ebp),%eax
db_printf+0x6:  pushl   %eax
db_printf+0x7:  pushl   $0
db_printf+0x9:  pushl   $0
db_printf+0xb:  pushl   $0x10
db_printf+0xd:  pushl          0x8(%ebp)
db_printf+0x10: call    kprintf
db> 
db> x/x db_printf+b 
db_printf+0xb:      75ff106a    
db> 

We presume the 3rd byte is the push value, so

db> w db_printf+b 75ff146a
db_printf+0xb               0x75ff106a = 0x75ff146a
db> x/i db_printf+b
db_printf+0xb:  pushl   $0x14

And then you're all set. I should make this a feature of the debugger,
but I just wanted to document it here first.

>Fix:
	I don't know enough about the vm system to say.
>Release-Note:
>Audit-Trail:
>Unformatted: