On Fri, Apr 01, 2016 at 11:29:14PM +0200, Vlastimil Babka wrote:
Might have been better as a separate migration patch and then a
compaction patch. It's prefixed mm/compaction, but most changed are
in mm/migrate.c
Indeed. The title is rather misleading but not sure it's a good idea
to separate compaction and migration part.
I will just resend to change the tile from "mm/compaction" to
"mm/migration".
Also I'm a bit uncomfortable how isolate_movable_page() blindly expects that
page->mapping->a_ops->isolate_page exists for PageMovable() pages.
What if it's a false positive on a PG_reclaim page? Can we rely on
PG_reclaim always (and without races) implying PageLRU() so that we
don't even attempt isolate_movable_page()?
For now, we shouldn't have such a false positive because PageMovable
checks page->_mapcount == PAGE_MOVABLE_MAPCOUNT_VALUE as well as PG_movable
under PG_lock.
But I read your question about user-mapped drvier pages so we cannot
use _mapcount anymore so I will find another thing. A option is this.
static inline int PageMovable(struct page *page)
{
int ret = 0;
struct address_space *mapping;
struct address_space_operations *a_op;
if (!test_bit(PG_movable, &(page->flags))
goto out;
mapping = page->mapping;
if (!mapping)
goto out;
a_op = mapping->a_op;
if (!aop)
goto out;
if (a_op->isolate_page)
ret = 1;
out:
return ret;
}
It works under PG_lock but with this, we need trylock_page to peek
whether it's movable non-lru or not for scanning pfn.
For avoiding that, we need another function to peek which just checks
PG_movable bit instead of all things.
/*
* If @page_locked is false, we cannot guarantee page->mapping's stability
* so just the function checks with PG_movable which could be false positive
* so caller should check it again under PG_lock to check a_ops->isolate_page.
*/
static inline int PageMovable(struct page *page, bool page_locked)
{
int ret = 0;
struct address_space *mapping;
struct address_space_operations *a_op;
if (!test_bit(PG_movable, &(page->flags))
goto out;
if (!page_locked) {
ret = 1;
goto out;
}
mapping = page->mapping;
if (!mapping)
goto out;
a_op = mapping->a_op;
if (!aop)
goto out;
if (a_op->isolate_page)
ret = 1;
out:
return ret;
}
Thanks for detail review, Vlastimil!
I will resend new versions after vacation in this week.