On Wed, Aug 19, 2020 at 04:05:50PM +0100, Matthew Wilcox (Oracle) wrote: > use the XArray directly instead of using the pagevec abstraction. > The code is simpler and more efficient. > > Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> > --- > mm/shmem.c | 61 +++++++++++++++++++++--------------------------------- > 1 file changed, 24 insertions(+), 37 deletions(-) > > diff --git a/mm/shmem.c b/mm/shmem.c > index a7bbc4ed9677..0f9f149f4b5e 100644 > --- a/mm/shmem.c > +++ b/mm/shmem.c > @@ -2659,53 +2659,40 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) > } > > /* > - * llseek SEEK_DATA or SEEK_HOLE through the page cache. > + * llseek SEEK_DATA or SEEK_HOLE through the page cache. We don't need > + * to get a reference on the page because this interface is racy anyway. > + * The page we find will have had the state at some point. For my non-native ear "will have had" is too complex ;-) > */ > static pgoff_t shmem_seek_hole_data(struct address_space *mapping, > pgoff_t index, pgoff_t end, int whence) > { > + XA_STATE(xas, &mapping->i_pages, index); > struct page *page; > - struct pagevec pvec; > - pgoff_t indices[PAGEVEC_SIZE]; > - bool done = false; > - int i; > > - pagevec_init(&pvec); > - pvec.nr = 1; /* start small: we may be there already */ > - while (!done) { > - pvec.nr = find_get_entries(mapping, index, > - pvec.nr, pvec.pages, indices); > - if (!pvec.nr) { > - if (whence == SEEK_DATA) > - index = end; > - break; > + rcu_read_lock(); > + if (whence == SEEK_DATA) { > + for (;;) { > + page = xas_find(&xas, end); > + if (xas_retry(&xas, page)) > + continue; > + if (!page || xa_is_value(page) || PageUptodate(page)) > + break; > } > - for (i = 0; i < pvec.nr; i++, index++) { > - if (index < indices[i]) { > - if (whence == SEEK_HOLE) { > - done = true; > - break; > - } > - index = indices[i]; > - } > - page = pvec.pages[i]; > - if (page && !xa_is_value(page)) { > - if (!PageUptodate(page)) > - page = NULL; > - } > - if (index >= end || > - (page && whence == SEEK_DATA) || > - (!page && whence == SEEK_HOLE)) { > - done = true; > + } else /* SEEK_HOLE */ { > + for (;;) { > + page = xas_next(&xas); > + if (xas_retry(&xas, page)) > + continue; > + if (!xa_is_value(page) && > + (!page || !PageUptodate(page))) > + break; > + if (xas.xa_index >= end) > break; > - } > } > - pagevec_remove_exceptionals(&pvec); > - pagevec_release(&pvec); > - pvec.nr = PAGEVEC_SIZE; > - cond_resched(); > } > - return index; > + rcu_read_unlock(); > + > + return xas.xa_index; > } > > static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence) > -- > 2.28.0 > > -- Sincerely yours, Mike.