From patchwork Thu Jun 1 09:32:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 9758923 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D33DF6038E for ; Thu, 1 Jun 2017 09:33:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B96C6284D1 for ; Thu, 1 Jun 2017 09:33:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE00E284F1; Thu, 1 Jun 2017 09:33:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D88CA284EA for ; Thu, 1 Jun 2017 09:33:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751728AbdFAJd3 (ORCPT ); Thu, 1 Jun 2017 05:33:29 -0400 Received: from mx2.suse.de ([195.135.220.15]:50914 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751506AbdFAJdX (ORCPT ); Thu, 1 Jun 2017 05:33:23 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 36B9FADFF; Thu, 1 Jun 2017 09:33:16 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 5F5121E35B7; Thu, 1 Jun 2017 11:33:12 +0200 (CEST) From: Jan Kara To: Cc: Hugh Dickins , David Howells , linux-afs@lists.infradead.org, Ryusuke Konishi , linux-nilfs@vger.kernel.org, Bob Peterson , cluster-devel@redhat.com, Jaegeuk Kim , linux-f2fs-devel@lists.sourceforge.net, tytso@mit.edu, linux-ext4@vger.kernel.org, Ilya Dryomov , "Yan, Zheng" , ceph-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, David Sterba , "Darrick J . Wong" , linux-xfs@vger.kernel.org, Nadia Yvette Chambers , Jan Kara Subject: [PATCH 30/35] mm: Implement find_get_entries_range() Date: Thu, 1 Jun 2017 11:32:40 +0200 Message-Id: <20170601093245.29238-31-jack@suse.cz> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20170601093245.29238-1-jack@suse.cz> References: <20170601093245.29238-1-jack@suse.cz> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement a variant of find_get_entries() that stops iterating at given index. Some callers want this, so let's provide the interface. Also it makes the interface consistent with find_get_pages(). Signed-off-by: Jan Kara --- include/linux/pagemap.h | 13 ++++++++++--- include/linux/pagevec.h | 12 ++++++++++-- mm/filemap.c | 32 ++++++++++++++++++++++++-------- mm/swap.c | 11 ++++++----- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 283d191c18be..df128a56f44b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -333,9 +333,16 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping, struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset); -unsigned find_get_entries(struct address_space *mapping, pgoff_t *start, - unsigned int nr_entries, struct page **entries, - pgoff_t *indices); +unsigned find_get_entries_range(struct address_space *mapping, pgoff_t *start, + pgoff_t end, unsigned int nr_entries, + struct page **entries, pgoff_t *indices); +static inline unsigned find_get_entries(struct address_space *mapping, + pgoff_t *start, unsigned int nr_entries, + struct page **entries, pgoff_t *indices) +{ + return find_get_entries_range(mapping, start, (pgoff_t)-1, nr_entries, + entries, indices); +} unsigned find_get_pages_range(struct address_space *mapping, pgoff_t *start, pgoff_t end, unsigned int nr_pages, struct page **pages); diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h index 3798c142338d..93308689d6a7 100644 --- a/include/linux/pagevec.h +++ b/include/linux/pagevec.h @@ -22,10 +22,18 @@ struct pagevec { void __pagevec_release(struct pagevec *pvec); void __pagevec_lru_add(struct pagevec *pvec); -unsigned pagevec_lookup_entries(struct pagevec *pvec, +unsigned pagevec_lookup_entries_range(struct pagevec *pvec, + struct address_space *mapping, + pgoff_t *start, pgoff_t end, + unsigned nr_entries, pgoff_t *indices); +static inline unsigned pagevec_lookup_entries(struct pagevec *pvec, struct address_space *mapping, pgoff_t *start, unsigned nr_entries, - pgoff_t *indices); + pgoff_t *indices) +{ + return pagevec_lookup_entries_range(pvec, mapping, start, (pgoff_t)-1, + nr_entries, indices); +} void pagevec_remove_exceptionals(struct pagevec *pvec); unsigned pagevec_lookup_range(struct pagevec *pvec, struct address_space *mapping, diff --git a/mm/filemap.c b/mm/filemap.c index de12b7355821..e55100459710 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1354,9 +1354,10 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, EXPORT_SYMBOL(pagecache_get_page); /** - * find_get_entries - gang pagecache lookup + * find_get_entries_range - gang pagecache lookup * @mapping: The address_space to search * @start: The starting page cache index + * @end: The final page cache index (inclusive) * @nr_entries: The maximum number of entries * @entries: Where the resulting entries are placed * @indices: The cache indices corresponding to the entries in @entries @@ -1376,9 +1377,9 @@ EXPORT_SYMBOL(pagecache_get_page); * find_get_entries() returns the number of pages and shadow entries which were * found. It also updates @start to index the next page for the traversal. */ -unsigned find_get_entries(struct address_space *mapping, - pgoff_t *start, unsigned int nr_entries, - struct page **entries, pgoff_t *indices) +unsigned find_get_entries_range(struct address_space *mapping, + pgoff_t *start, pgoff_t end, unsigned int nr_entries, + struct page **entries, pgoff_t *indices) { void **slot; unsigned int ret = 0; @@ -1390,6 +1391,9 @@ unsigned find_get_entries(struct address_space *mapping, rcu_read_lock(); radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, *start) { struct page *head, *page; + + if (iter.index > end) + break; repeat: page = radix_tree_deref_slot(slot); if (unlikely(!page)) @@ -1425,13 +1429,25 @@ unsigned find_get_entries(struct address_space *mapping, export: indices[ret] = iter.index; entries[ret] = page; - if (++ret == nr_entries) - break; + if (++ret == nr_entries) { + *start = indices[ret - 1] + 1; + goto out; + } } + + /* + * We come here when there is no page beyond @end. We take care to not + * overflow the index @start as it confuses some of the callers. This + * breaks the iteration when there is page at index -1 but that is + * already broken anyway. + */ + if (end == (pgoff_t)-1) + *start = (pgoff_t)-1; + else + *start = end + 1; +out: rcu_read_unlock(); - if (ret) - *start = indices[ret - 1] + 1; return ret; } diff --git a/mm/swap.c b/mm/swap.c index 6ba3dab6e905..88c7eb4e97db 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -889,10 +889,11 @@ void __pagevec_lru_add(struct pagevec *pvec) EXPORT_SYMBOL(__pagevec_lru_add); /** - * pagevec_lookup_entries - gang pagecache lookup + * pagevec_lookup_entries_range - gang pagecache lookup * @pvec: Where the resulting entries are placed * @mapping: The address_space to search * @start: The starting entry index + * @end: The final entry index (inclusive) * @nr_entries: The maximum number of entries * @indices: The cache indices corresponding to the entries in @pvec * @@ -908,13 +909,13 @@ EXPORT_SYMBOL(__pagevec_lru_add); * pagevec_lookup_entries() returns the number of entries which were * found. It also updates @start to index the next page for the traversal. */ -unsigned pagevec_lookup_entries(struct pagevec *pvec, +unsigned pagevec_lookup_entries_range(struct pagevec *pvec, struct address_space *mapping, - pgoff_t *start, unsigned nr_pages, + pgoff_t *start, pgoff_t end, unsigned nr_pages, pgoff_t *indices) { - pvec->nr = find_get_entries(mapping, start, nr_pages, - pvec->pages, indices); + pvec->nr = find_get_entries_range(mapping, start, end, nr_pages, + pvec->pages, indices); return pagevec_count(pvec); }