Fixed a major bug that caused various pmap related panics, hangs, and reboots.

The i386 pmap module uses a special area of kernel virtual memory for mapping
of page tables pages when it needs to modify another process's virtual
address space. It's called the 'alternate page table map'. There is only one
of them and it's expected that only one process will be using it at once and
that the operation is atomic.
When the merged VM/buffer cache was implemented over a year ago, it became
necessary to rundown VM pages at I/O completion. The unfortunate and
unforeseen side effect of this is that pmap functions are now called at bio
interrupt time. If there happend to be a process using the alternate page
table map when this I/O completion occurred, it was possible for a different
process's address space to be switched into the alternate page table map -
leaving the current pmap process with the wrong address space mapped when
the interrupt completed. This resulted in BAD things happening like pages
being mapped or removed from the wrong address space, etc.. Since a very
common case of a process modifying another process's address space is during
fork when the kernel stack is inserted, one of the most common manifestations
of this bug was the kernel stack not being mapped properly, resulting in a
silent hang or reboot. This made it VERY difficult to troubleshoot this bug
(I've been trying to figure out the cause of this for >6 months). Fortunately,
the set of conditions that must be true before this problem occurs is
sufficiently rare enough that most people never saw the bug occur. As I/O
rates increase, however, so does the frequency of the crashes. This problem
used to kill wcarchive about every 10 days, but in more recent times when
the traffic exceeded >100GB/day, the machine could barely manage 6 hours of
uptime.
The fix is to make certain that no process has the pages mapped that are
involved in the I/O, before the I/O is started. The pages are made busy, so
no process will be able to map them, either, until the I/O has finished.
This side-steps the issue by still allowing the pmap functions to be called
at interrupt time, but also assuring that the alternate page table map won't
be switched.
Unfortunately, this appears to not be the only cause of this problem. :-(

Reviewed by:	dyson
This commit is contained in:
David Greenman 1996-06-30 05:17:08 +00:00
parent dcca5a532d
commit 7c818168d5

View File

@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: vfs_bio.c,v 1.92 1996/05/31 00:41:37 dyson Exp $
* $Id: vfs_bio.c,v 1.93 1996/06/14 11:01:27 asami Exp $
*/
/*
@ -1619,8 +1619,8 @@ vfs_busy_pages(struct buf * bp, int clear_modify)
obj->paging_in_progress++;
m->busy++;
}
vm_page_protect(m, VM_PROT_NONE);
if (clear_modify) {
vm_page_protect(m, VM_PROT_READ);
vm_page_set_validclean(m,
(vm_offset_t) (foff & PAGE_MASK), resid);
} else if (bp->b_bcount >= PAGE_SIZE) {