On Fri, Aug 27, 2021 at 03:58:13PM +0100, Joao Martins wrote:
> @@ -2252,16 +2265,25 @@ static int __gup_device_huge(unsigned long pfn,
> unsigned long addr,
> ret = 0;
> break;
> }
> - SetPageReferenced(page);
> - pages[*nr] = page;
> - if (unlikely(!try_grab_page(page, flags))) {
> - undo_dev_pagemap(nr, nr_start, flags, pages);
> +
> + head = compound_head(page);
> + /* @end is assumed to be limited at most one compound page */
> + if (PageHead(head))
> + next = end;
> + refs = record_subpages(page, addr, next, pages + *nr);
> +
> + SetPageReferenced(head);
> + if (unlikely(!try_grab_compound_head(head, refs, flags))) {
I was thinking about this some more, and this ordering doesn't seem
like a good idea. We shouldn't be looking at any part of the struct
page without holding the refcount, certainly not the compound_head()
The only optimization that might work here is to grab the head, then
compute the extent of tail pages and amalgamate them. Holding a ref on
the head also secures the tails.
Which also means most of what I was suggesting isn't going to work
anyhow.
Jason