Date: Sat, 06 Aug 2005 20:12:55 -0700 From: Julian Elischer <julian@elischer.org> To: Martin Nilsson <martin@gneto.com> Cc: freebsd-current@freebsd.org Subject: Re: Something is very wrong with disk caching in 7.0 Message-ID: <42F57C37.3080900@elischer.org> In-Reply-To: <42F4730C.6040204@gneto.com> References: <42F45923.2080401@gneto.com> <42F4659F.5030407@gneto.com> <42F46942.7030005@elischer.org> <42F4730C.6040204@gneto.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------040706020200020108010809 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Martin Nilsson wrote: > Julian Elischer wrote: > try this patch --------------040706020200020108010809 Content-Type: text/plain; name="pageout.diff2" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pageout.diff2" Index: sys/vm/vm_pageout.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_pageout.c,v retrieving revision 1.268 diff -u -r1.268 vm_pageout.c --- sys/vm/vm_pageout.c 7 Jan 2005 02:29:27 -0000 1.268 +++ sys/vm/vm_pageout.c 30 Jul 2005 03:12:37 -0000 @@ -5,6 +5,8 @@ * All rights reserved. * Copyright (c) 1994 David Greenman * All rights reserved. + * Copyright (c) 2005 Yahoo! Technologies Norway AS + * All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. @@ -210,6 +212,16 @@ static void vm_pageout_page_stats(void); /* + * Experimental VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK option, which will cause + * pagedaemon to fall back to blocking locking of vm objects if nonblocking + * lock attempt failed. Lock order violation is avoided by unlocking + * the page queues before locking the object. marker pages are used + * to detect changes and allow for continued page queue traversal even + * when changes had occurred. + */ +#define VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + +/* * vm_pageout_clean: * * Clean the page and remove it from the laundry. @@ -750,8 +762,37 @@ * queue, most likely are being paged out. */ if (!VM_OBJECT_TRYLOCK(object)) { +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + /* + * Cannot lock object while holding page queue lock. + * Depend on both struct vm_object and normal + * struct vm_page being type stable and sanity + * check after reobtaining page queue lock. + */ + TAILQ_INSERT_AFTER(&vm_page_queues[PQ_INACTIVE].pl, + m, &marker, pageq); + vm_page_unlock_queues(); + VM_OBJECT_LOCK(object); + vm_page_lock_queues(); + /* Page queue might have changed. */ + next = TAILQ_NEXT(&marker, pageq); + if (m->queue != PQ_INACTIVE || + m->object != object || + m->hold_count != 0 || + &marker != TAILQ_NEXT(m, pageq)) { + /* Page changed. */ + VM_OBJECT_UNLOCK(object); + TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, + &marker, pageq); + addl_page_shortage++; + continue; + } + TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, + &marker, pageq); +#else addl_page_shortage++; continue; +#endif } if (m->busy || (m->flags & PG_BUSY)) { VM_OBJECT_UNLOCK(object); @@ -1024,10 +1065,44 @@ next = TAILQ_NEXT(m, pageq); object = m->object; +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + if ((m->flags & PG_MARKER) != 0) { + m = next; + continue; + } +#endif if (!VM_OBJECT_TRYLOCK(object)) { +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + /* + * Cannot lock object while holding page queue lock. + * Depend on both struct vm_object and normal + * struct vm_page being type stable and sanity + * check after reobtaining page queue lock. + */ + TAILQ_INSERT_AFTER(&vm_page_queues[PQ_ACTIVE].pl, + m, &marker, pageq); + vm_page_unlock_queues(); + VM_OBJECT_LOCK(object); + vm_page_lock_queues(); + /* Page queue might have changed. */ + next = TAILQ_NEXT(&marker, pageq); + if (m->queue != PQ_ACTIVE || + m->object != object || + &marker != TAILQ_NEXT(m, pageq)) { + /* Page changed. */ + VM_OBJECT_UNLOCK(object); + TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, + &marker, pageq); + m = next; + continue; + } + TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, + &marker, pageq); +#else vm_pageq_requeue(m); m = next; continue; +#endif } /* @@ -1264,6 +1339,9 @@ vm_pageout_page_stats() { vm_object_t object; +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + struct vm_page marker; +#endif vm_page_t m,next; int pcount,tpcount; /* Number of pages to check */ static int fullintervalcount = 0; @@ -1287,6 +1365,16 @@ fullintervalcount = 0; } +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + /* + * Initialize our marker + */ + bzero(&marker, sizeof(marker)); + marker.flags = PG_BUSY | PG_FICTITIOUS | PG_MARKER; + marker.queue = PQ_INACTIVE; + marker.wire_count = 1; +#endif + m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl); while ((m != NULL) && (pcount-- > 0)) { int actcount; @@ -1296,10 +1384,45 @@ next = TAILQ_NEXT(m, pageq); object = m->object; + +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + if ((m->flags & PG_MARKER) != 0) { + m = next; + continue; + } +#endif if (!VM_OBJECT_TRYLOCK(object)) { +#ifdef VM_PAGEOUT_FORCE_BLOCKING_OBJLOCK + /* + * Cannot lock object while holding page queue lock. + * Depend on both struct vm_object and normal + * struct vm_page being type stable and sanity + * check after reobtaining page queue lock. + */ + TAILQ_INSERT_AFTER(&vm_page_queues[PQ_ACTIVE].pl, + m, &marker, pageq); + vm_page_unlock_queues(); + VM_OBJECT_LOCK(object); + vm_page_lock_queues(); + /* Page queue might have changed. */ + next = TAILQ_NEXT(&marker, pageq); + if (m->queue != PQ_ACTIVE || + m->object != object || + &marker != TAILQ_NEXT(m, pageq)) { + /* Page changed. */ + VM_OBJECT_UNLOCK(object); + TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, + &marker, pageq); + m = next; + continue; + } + TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, + &marker, pageq); +#else vm_pageq_requeue(m); m = next; continue; +#endif } /* --------------040706020200020108010809--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?42F57C37.3080900>