Date: Sun, 10 Dec 2000 16:03:55 -0800 (PST) From: Matt Dillon <dillon@earth.backplane.com> To: Philipp Mergenthaler <un1i@rz.uni-karlsruhe.de> Cc: freebsd-current@freebsd.org Subject: Re: panic: vm_pageout_flush: partially dirty page Message-ID: <200012110003.eBB03t887967@earth.backplane.com> References: <20001210033546.A13896@rz.uni-karlsruhe.de>
next in thread | previous in thread | raw e-mail | index | archive | help
Phillipp, could you do me a favor and try this patch instead of removing the KASSERT? That is, keep the original KASSERT, apply this patch to your -current instead, and see if you still get the panic. This patch is relative to -current. What it does is clear the dirty bits for the portion of the fragment being truncated off. If the resulting page is entirely clean, then fine. If it is partially dirty then we make the whole thing dirty in case it was mapped. I believe what was happening was that there is a small file, around 1K, which is clean, gets something appended to it with write() (dirtying a big chunk of the page but not the first 1K or so), and then gets truncated small again. The buffer cache then believes, correctly, that the (now 1K) buffer is no longer dirty and can be thrown away. However. the backing vm_page_t is still marked partially dirty because the truncate operation didn't undo the dirty bits for the section that was truncated. This results in a partially dirty vm_page_t that is not associated with any buffer. It hits the VM flushing code and panics because mapped dirty pages are supposed to either be 100% clean or 100% dirty, not something inbetween. -Matt Index: vm/vnode_pager.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vnode_pager.c,v retrieving revision 1.124 diff -u -r1.124 vnode_pager.c --- vnode_pager.c 2000/07/11 22:07:57 1.124 +++ vnode_pager.c 2000/12/10 23:53:53 @@ -300,10 +300,29 @@ m = vm_page_lookup(object, OFF_TO_IDX(nsize)); if (m) { + int base = (int)nsize & PAGE_MASK; + int size = PAGE_SIZE - base; + + /* + * Clear out partial-page garbage in case + * the page has been mapped. + */ kva = vm_pager_map_page(m); - bzero((caddr_t) kva + (nsize & PAGE_MASK), - (int) (round_page(nsize) - nsize)); + bzero((caddr_t)kva + base, size); vm_pager_unmap_page(kva); + + /* + * Clear out partial-page dirty bits. This + * has the side effect of setting the valid + * bits, but that is ok. There are a bunch + * of places in the VM system where we expected + * m->dirty == VM_PAGE_BITS_ALL. The file EOF + * case is one of them. If the page is still + * partially dirty, make it fully dirty. + */ + vm_page_set_validclean(m, base, size); + if (m->dirty != 0) + m->dirty = VM_PAGE_BITS_ALL; } } } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200012110003.eBB03t887967>