cvs commit: src/sys/fs/nwfs nwfs_io.c src/sys/fs/smbfs smbfs_io.c src/sys/fs/specfs spec_vnops.c src/sys/kern uipc_syscalls.c vfs_bio.c src/sys/nfsclient nfs_bio.c src/sys/vm swap_page

Alan Cox alc at cs.rice.edu
Thu May 6 13:08:42 PDT 2004


On Fri, May 07, 2004 at 01:30:27AM +1000, Bruce Evans wrote:
> On Wed, 5 May 2004, Alan Cox wrote:
> 
> > alc         2004/05/05 22:03:24 PDT
> >
> >   FreeBSD src repository
> >
> >   Modified files:
> >     sys/fs/nwfs          nwfs_io.c
> >     sys/fs/smbfs         smbfs_io.c
> >     sys/fs/specfs        spec_vnops.c
> >     sys/kern             uipc_syscalls.c vfs_bio.c
> >     sys/nfsclient        nfs_bio.c
> >     sys/vm               swap_pager.c vm_fault.c vnode_pager.c
> >   Log:
> >   Make vm_page's PG_ZERO flag immutable between the time of the page's
> >   allocation and deallocation.  This flag's principal use is shortly after
> >   allocation.  For such cases, clearing the flag is pointless.  The only
> >   unusual use of PG_ZERO is in vfs_bio_clrbuf().  However, allocbuf() never
> >   requests a prezeroed page.  So, vfs_bio_clrbuf() never sees a prezeroed
>                                                      ^^^^^ rarely(?)
> >   page.
> >
> >   Reviewed by:    tegge@
> 
> The request for a prezeroed page is just a preference, so vfs_bio_clrbuf()
> certainly gets prezeroed pages.  This happens whenever there are only
> prezeroed pages to find.  I think vfs_bio_clrbuf() sees them too.  It
> saw them at least once a few years ago when my debugging code for this
> finally triggered.  My kernel at the time had colorizing optimizations
> that probably made using a prezeroed page more likely.

No, HEAD and RELENG_4 differ.  You are describing RELENG_4.  In HEAD,
the flag is only returned if a zeroed page is requested:

	flags = PG_BUSY;
	if (m->flags & PG_ZERO) {
		vm_page_zero_count--;
		if (req & VM_ALLOC_ZERO)
			flags = PG_ZERO | PG_BUSY;
	}

Why did I do this?  Consider the RELENG_4 implementation of PG_ZERO
and VM_ALLOC_ZERO.  The concept in RELENG_4 was to track the state of
a page from birth to death.  See vm/vm_page.h revision 1.55.  This was
never finished and enabled.  We were, however, left with a model in
which every caller to vm_page_alloc() was (potentially) responsible 
for clearing PG_ZERO whether they wanted a prezeroed page or not.  In
other words, if the caller's use of the page was going to dirty it,
the caller was always responsible for clearing the flag.

What was the potential gain of this model?  If a prezeroed page was
allocated but never dirtied before being freed, it would automatically
go back to the prezeroed queue.  How likely is this?  Note that the
most common case is captured "manually" by the pmap.  When the pmap
frees a page table page, it knows that the page is zeroed.  So, it
directs vm_page.c to place the page in the prezeroed queue.
  
What is the downside of this model?  Clearing the flag requires an
atomic memory op in RELENG_4 and a mutex in HEAD.

Given that atomic memory ops are getting more expensive with each
successive generation of Intel CPU, this is a dubious tradeoff.

In terms of programming model, its too easy for a driver, module, file
system, etc. by the average joe to forget to clear PG_ZERO, causing
havoc. 

Thus, prior to this commit, only those callers to vm_page_alloc() that
explicitly asked for a prezeroed page were responsible for clearing
PG_ZERO.  Now, no caller is.

Ultimately, I would like to reenable the RELENG_4-like behavior of
VM_ALLOC_ZERO.  In other words, PG_ZERO can be returned regardless of
VM_ALLOC_ZERO.  Before that happens, vfs_bio_clrbuf() needs further
scrutiny. 

> The PG_ZERO optimizations in vfs_bio_clrbuf() were just worse than useless
> because they rarely applied (and they break immutability here).

Agreed.

Regards,
Alan


More information about the cvs-src mailing list