On 2/5/21 4:11 AM, John Hubbard wrote: > On 2/4/21 12:24 PM, Joao Martins wrote: >> Add an helper that iterates over head pages in a list of pages. It >> essentially counts the tails until the next page to process has a >> different head that the current. This is going to be used by >> unpin_user_pages() family of functions, to batch the head page refcount >> updates once for all passed consecutive tail pages. >> >> Suggested-by: Jason Gunthorpe <jgg@xxxxxxxxxx> >> Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> >> --- >> mm/gup.c | 29 +++++++++++++++++++++++++++++ >> 1 file changed, 29 insertions(+) >> >> diff --git a/mm/gup.c b/mm/gup.c >> index d68bcb482b11..d1549c61c2f6 100644 >> --- a/mm/gup.c >> +++ b/mm/gup.c >> @@ -215,6 +215,35 @@ void unpin_user_page(struct page *page) >> } >> EXPORT_SYMBOL(unpin_user_page); >> >> +static inline void compound_next(unsigned long i, unsigned long npages, >> + struct page **list, struct page **head, >> + unsigned int *ntails) >> +{ >> + struct page *page; >> + unsigned int nr; >> + >> + if (i >= npages) >> + return; >> + >> + list += i; >> + npages -= i; > > It is worth noting that this is slightly more complex to read than it needs to be. > You are changing both endpoints of a loop at once. That's hard to read for a human. > And you're only doing it in order to gain the small benefit of being able to > use nr directly at the end of the routine. > > If instead you keep npages constant like it naturally wants to be, you could > just do a "(*ntails)++" in the loop, to take care of *ntails. > I didn't do it as such as I would need to deref @ntails per iteration, so it felt more efficient to do as above. On a second thought, I could alternatively do the following below, thoughts? diff --git a/mm/gup.c b/mm/gup.c index d68bcb482b11..8defe4f670d5 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -215,6 +215,32 @@ void unpin_user_page(struct page *page) } EXPORT_SYMBOL(unpin_user_page); +static inline void compound_next(unsigned long i, unsigned long npages, + struct page **list, struct page **head, + unsigned int *ntails) +{ + struct page *page; + unsigned int nr; + + if (i >= npages) + return; + + page = compound_head(list[i]); + for (nr = i + 1; nr < npages; nr++) { + if (compound_head(list[nr]) != page) + break; + } + + *head = page; + *ntails = nr - i; +} + > However, given that the patch is correct and works as-is, the above is really just > an optional idea, so please feel free to add: > > Reviewed-by: John Hubbard <jhubbard@xxxxxxxxxx> > > Thanks! Hopefully I can retain that if the snippet above is preferred? Joao