From owner-svn-src-head@FreeBSD.ORG Thu Nov 18 21:09:02 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 757161065673; Thu, 18 Nov 2010 21:09:02 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6809F8FC1B; Thu, 18 Nov 2010 21:09:02 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oAIL92Of045041; Thu, 18 Nov 2010 21:09:02 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oAIL92lb045036; Thu, 18 Nov 2010 21:09:02 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201011182109.oAIL92lb045036@svn.freebsd.org> From: Konstantin Belousov Date: Thu, 18 Nov 2010 21:09:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r215471 - head/sys/vm X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Nov 2010 21:09:02 -0000 Author: kib Date: Thu Nov 18 21:09:02 2010 New Revision: 215471 URL: http://svn.freebsd.org/changeset/base/215471 Log: vm_pageout_flush() might cache the pages that finished write to the backing storage. Such pages might be then reused, racing with the assert in vm_object_page_collect_flush() that verified that dirty pages from the run (most likely, pages with VM_PAGER_AGAIN status) are write-protected still. In fact, the page indexes for the pages that were removed from the object page list should be ignored by vm_object_page_clean(). Return the length of successfully written run from vm_pageout_flush(), that is, the count of pages between requested page and first page after requested with status VM_PAGER_AGAIN. Supply the requested page index in the array to vm_pageout_flush(). Use the returned run length to forward the index of next page to clean in vm_object_page_clean(). Reported by: avg Reviewed by: alc MFC after: 1 week Modified: head/sys/vm/vm_contig.c head/sys/vm/vm_object.c head/sys/vm/vm_pageout.c head/sys/vm/vm_pageout.h Modified: head/sys/vm/vm_contig.c ============================================================================== --- head/sys/vm/vm_contig.c Thu Nov 18 21:02:40 2010 (r215470) +++ head/sys/vm/vm_contig.c Thu Nov 18 21:09:02 2010 (r215471) @@ -140,7 +140,7 @@ vm_contig_launder_page(vm_page_t m, vm_p object->type == OBJT_DEFAULT) { vm_page_unlock_queues(); m_tmp = m; - vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC); + vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC, 0, NULL); VM_OBJECT_UNLOCK(object); vm_page_lock_queues(); return (0); Modified: head/sys/vm/vm_object.c ============================================================================== --- head/sys/vm/vm_object.c Thu Nov 18 21:02:40 2010 (r215470) +++ head/sys/vm/vm_object.c Thu Nov 18 21:09:02 2010 (r215471) @@ -884,30 +884,9 @@ vm_object_page_collect_flush(vm_object_t index = (maxb + i) + 1; ma[index] = maf[i]; } - runlen = maxb + maxf + 1; - vm_pageout_flush(ma, runlen, pagerflags); - for (i = 0; i < runlen; i++) { - if (ma[i]->dirty != 0) { - KASSERT((ma[i]->flags & PG_WRITEABLE) == 0, - ("vm_object_page_collect_flush: page %p is not write protected", - ma[i])); - } - } - for (i = 0; i < maxf; i++) { - if (ma[i + maxb + 1]->dirty != 0) { - /* - * maxf will end up being the actual number of pages - * we wrote out contiguously, non-inclusive of the - * first page. We do not count look-behind pages. - */ - if (maxf > i) { - maxf = i; - break; - } - } - } - return (maxf + 1); + vm_pageout_flush(ma, maxb + maxf + 1, pagerflags, maxb + 1, &runlen); + return (runlen); } /* Modified: head/sys/vm/vm_pageout.c ============================================================================== --- head/sys/vm/vm_pageout.c Thu Nov 18 21:02:40 2010 (r215470) +++ head/sys/vm/vm_pageout.c Thu Nov 18 21:09:02 2010 (r215471) @@ -438,7 +438,7 @@ more: /* * we allow reads during pageouts... */ - return (vm_pageout_flush(&mc[page_base], pageout_count, 0)); + return (vm_pageout_flush(&mc[page_base], pageout_count, 0, 0, NULL)); } /* @@ -449,14 +449,17 @@ more: * reference count all in here rather then in the parent. If we want * the parent to do more sophisticated things we may have to change * the ordering. + * + * Returned runlen is the count of pages between mreq and first + * page after mreq with status VM_PAGER_AGAIN. */ int -vm_pageout_flush(vm_page_t *mc, int count, int flags) +vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen) { vm_object_t object = mc[0]->object; int pageout_status[count]; int numpagedout = 0; - int i; + int i, runlen; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED); @@ -482,6 +485,7 @@ vm_pageout_flush(vm_page_t *mc, int coun vm_pager_put_pages(object, mc, count, flags, pageout_status); + runlen = count - mreq; for (i = 0; i < count; i++) { vm_page_t mt = mc[i]; @@ -513,6 +517,8 @@ vm_pageout_flush(vm_page_t *mc, int coun vm_page_unlock(mt); break; case VM_PAGER_AGAIN: + if (i >= mreq && i - mreq < runlen) + runlen = i - mreq; break; } @@ -532,6 +538,8 @@ vm_pageout_flush(vm_page_t *mc, int coun } } } + if (prunlen != NULL) + *prunlen = runlen; return (numpagedout); } Modified: head/sys/vm/vm_pageout.h ============================================================================== --- head/sys/vm/vm_pageout.h Thu Nov 18 21:02:40 2010 (r215470) +++ head/sys/vm/vm_pageout.h Thu Nov 18 21:09:02 2010 (r215471) @@ -102,7 +102,7 @@ extern void vm_waitpfault(void); #ifdef _KERNEL boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *); -int vm_pageout_flush(vm_page_t *, int, int); +int vm_pageout_flush(vm_page_t *, int, int, int, int *); void vm_pageout_oom(int shortage); boolean_t vm_pageout_page_lock(vm_page_t, vm_page_t *); void vm_contig_grow_cache(int, vm_paddr_t, vm_paddr_t);