Re: anon_vma RFC2

Hugh Dickins
2004-03-13T17:24:20Z

On Sat, 13 Mar 2004, Linus Torvalds wrote:
>
> Ok, guys,
> how about this anon-page suggestion?

What you describe is pretty much exactly what my anobjrmap patch
from a year ago did. I'm currently looking through that again
to bring it up to date.

> I'm a bit nervous about the complexity issues in Andrea's current setup,
> so I've been thinking about Rik's per-mm thing. And I think that there is
> one very simple approach, which should work fine, and should have minimal
> impact on the existing setup exactly because it is so simple.
>
> Basic setup:
> - each anonymous page is associated with exactly _one_ virtual address,
> in a "anon memory group".
>
> We put the virtual address (shifted down by PAGE_SHIFT) into
> "page->index". We put the "anon memory group" pointer into
> "page->mapping". We have a PAGE_ANONYMOUS flag to tell the
> rest of the world about this.

It's a bit more complicated because page->mapping currently contains
&swapper_space if PageSwapCache(page) - indeed, at present that's
exactly what PageSwapCache(page) tests. So I reintroduced a
PageSwapCache(page) flagbit, avoid the very few places where mapping
pointing to swapper_space was actually useful, and use page->private
instead of page->index for the swp_entry_t.

(Andrew did point out that we could reduce the scale of the mods by
reusing page->list fields instead of mapping/index; but mapping/index
are the natural fields to use, and Andrew now has other changes in
-mm which remove page->list: so the original choice looks right again.)

> for_each_entry(mm, mmlist->anon_mms, anon_mm) {
> .. look up page in page tables in "mm, address" ..
> .. most of the time we may not even need to look ..
> .. up the "vma" at all, just walk the page tables ..
> }

I believe page_referenced() can just walk the page tables,
but try_to_unmap() needs vma to check VM_LOCKED (we're thinking
of other ways to avoid that, but they needn't get mixed into this)
and for flushing cache and tlb (perhaps avoidable on some arches?
I've not checked, and again that would be an optimization to
consider later, not mix in at this stage).

> The only problem is mremap() after a fork(), and hell, we know that's a
> special case anyway, and let's just add a few lines to copy_one_pte(),
> which basically does:
>
> if (PageAnonymous(page) && page->count > 1) {
> newpage = alloc_page();
> copy_page(page, newpage);
> page = newpage;
> }
> /* Move the page to the new address */
> page->index = address >> PAGE_SHIFT;
>
> and now we have zero special cases.

That's always been a fallback solution, I was just a little too ashamed
to propose it originally - seems a little wrong to waste whole pages
rather than wasting a few bytes of data structure trying to track them:
though the pages are pageable unlike any data structure we come up with.

I think we have page_table_lock in copy_one_pte, so won't want to do
it quite like that. It won't matter at all if pages are transiently
untrackable. Might want to do something like make_pages_present
afterwards (but it should only be COWing instantiated pages; and
does need to COW pages currently on swap too).

There's probably an issue with Alan's strict commit memory accounting,
if the mapping is readonly; but so long as we get that counting right,
I don't think it's really going to matter at all if we sometimes fail
an mremap for that reason - but probably need to avoid mistaking the
common case (mremap of own area) for the rare case which needs this
copying (mremap of inherited area).

Hugh