Skip site navigation (1)Skip section navigation (2)
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>