From owner-freebsd-stable Fri Aug 14 04:48:15 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id EAA10245 for freebsd-stable-outgoing; Fri, 14 Aug 1998 04:48:15 -0700 (PDT) (envelope-from owner-freebsd-stable@FreeBSD.ORG) Received: from implode.root.com (implode.root.com [198.145.90.17]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id EAA10240; Fri, 14 Aug 1998 04:48:13 -0700 (PDT) (envelope-from root@implode.root.com) Received: from implode.root.com (localhost [127.0.0.1]) by implode.root.com (8.8.5/8.8.5) with ESMTP id EAA23436; Fri, 14 Aug 1998 04:47:10 -0700 (PDT) Message-Id: <199808141147.EAA23436@implode.root.com> To: Terry Lambert cc: mike@smith.net.au, peter@sirius.com, mrcpu@internetcds.com, hackers@FreeBSD.ORG, stable@FreeBSD.ORG Subject: Re: vmopar state in 2.2.7? In-reply-to: Your message of "Fri, 14 Aug 1998 02:27:05 -0000." <199808140227.TAA25476@usr02.primenet.com> From: David Greenman Reply-To: dg@root.com Date: Fri, 14 Aug 1998 04:47:10 -0700 Sender: owner-freebsd-stable@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG >In the second case, 1261, the consequences could be bad. In fact, >the consequences of sleeping at all could be bad. The reason it >seems to work around the problem for you is that the page causing >the problem is not the first page on the list and start has been >incremented. Because start is not decremented before the "goto again", >the calculation on line 1207: > > again: > size = end - start; > if (size > 4 || size >= object->size / 4) { > >Bogusly omits the page which was just obtained. This means that > > vm_page_protect(p, VM_PROT_NONE); > PAGE_WAKEUP(p); > vm_page_free(p); > >is never called. > >The net result is that pages are left hanging out in space, but the system >thinks they have been reclaimed. Err, it doesn't "omit the page which was just obtained". First off, pages aren't obtained; all that happens is a pointer to them is gotten - they are still on the object page list. For optimal performance, there are two ways that the code will traverse the resident pages in the object. The first is the case where the object either contains a small number of pages or if all the pages should be removed. In this case, it just accesses the unsorted object resident page list. Since this list contains all of the pages in a resident object, the code must check the offset of the pages to ensure that they are within the proper range that is being removed. Pages that are wired or dirty are skipped. If while doing this a busy page is encountered, then the system must wait for the page to become not busy. While sleeping, the order of pages might have changed in the list, however, so it is necessary to start over again from the beginning of the object page list. "start" isn't and can't be updated since the order of pages that are removed is random. The second method is to look up the page on the object page hash list. This has somewhat higher overhead, but is more efficient when dealing with a small number of pages in an object that has a large number of resident pages. Since in this case we process the pages sequentially in the start to end range, we can increment start as each page is removed (or skipped as the case may be). If the page is busy, then start isn't incremented and thus the 'goto again' will begin with the page which was just slept on. Once again, the bug isn't in the code there. The effects that have been described suggest a missing wakeup. I believe the attached patches should fix the problem. -DG David Greenman Co-founder/Principal Architect, The FreeBSD Project Index: nfs/nfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_bio.c,v retrieving revision 1.28.2.7 diff -c -r1.28.2.7 nfs_bio.c *** nfs_bio.c 1998/01/28 00:26:54 1.28.2.7 --- nfs_bio.c 1998/08/14 11:42:02 *************** *** 131,136 **** --- 131,140 ---- m->flags |= PG_BUSY; m->busy--; + if (m->busy == 0 && (m->flags & PG_WANTED)) { + m->flags &= ~PG_WANTED; + wakeup(m); + } if (error && (auio.uio_resid == MAXBSIZE)) return VM_PAGER_ERROR; Index: vm/vnode_pager.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vnode_pager.c,v retrieving revision 1.65.2.2 diff -c -r1.65.2.2 vnode_pager.c *** vnode_pager.c 1997/05/28 18:26:46 1.65.2.2 --- vnode_pager.c 1998/08/14 11:43:06 *************** *** 963,970 **** if (i < ncount) { rtvals[i] = VM_PAGER_OK; } ! if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED)) wakeup(m[i]); } return rtvals[0]; } --- 963,972 ---- if (i < ncount) { rtvals[i] = VM_PAGER_OK; } ! if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED)) { ! m[i]->flags &= ~PG_WANTED; wakeup(m[i]); + } } return rtvals[0]; } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-stable" in the body of the message