On Wed, Nov 04, 2020 at 04:30:05PM -0500, Kent Overstreet wrote: > On Wed, Nov 04, 2020 at 08:42:03PM +0000, Matthew Wilcox (Oracle) wrote: > > Increasing the batch size runs into diminishing returns. It's probably > > better to make, eg, three calls to filemap_get_pages() than it is to > > call into kmalloc(). > > I have to disagree. Working with PAGEVEC_SIZE pages is eventually going to be > like working with 4k pages today, and have you actually read the slub code for > the kmalloc fast path? It's _really_ fast, there's no atomic operations and it > doesn't even have to disable preemption - which is why you never see it showing > up in profiles ever since we switched to slub. > > It would however be better to have a standard abstraction for this rather than > open coding it - perhaps adding it to the pagevec code. Please don't just drop > it, though. I have the beginnings of a patch for that, but I got busy with other stuff and didn't finish it. diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h index 081d934eda64..b067d8aab874 100644 --- a/include/linux/pagevec.h +++ b/include/linux/pagevec.h @@ -18,13 +18,21 @@ struct page; struct address_space; struct pagevec { - unsigned char nr; - bool percpu_pvec_drained; - struct page *pages[PAGEVEC_SIZE]; + union { + struct { + unsigned char sz; + unsigned char nr; + bool percpu_pvec_drained; + struct page *pages[]; + }; + void *__p[PAGEVEC_SIZE + 1]; + }; }; void __pagevec_release(struct pagevec *pvec); void __pagevec_lru_add(struct pagevec *pvec); +struct pagevec *pagevec_alloc(unsigned int sz, gfp_t gfp); +void pagevec_free(struct pagevec *); unsigned pagevec_lookup_entries(struct pagevec *pvec, struct address_space *mapping, pgoff_t start, unsigned nr_entries, @@ -54,6 +62,7 @@ static inline unsigned pagevec_lookup_tag(struct pagevec *pvec, static inline void pagevec_init(struct pagevec *pvec) { + pvec->sz = PAGEVEC_SIZE; pvec->nr = 0; pvec->percpu_pvec_drained = false; } @@ -63,6 +72,11 @@ static inline void pagevec_reinit(struct pagevec *pvec) pvec->nr = 0; } +static inline unsigned pagevec_size(struct pagevec *pvec) +{ + return pvec->sz; +} + static inline unsigned pagevec_count(struct pagevec *pvec) { return pvec->nr;