linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@infradead.org>
To: linux-fsdevel@vger.kernel.org
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: [PATCH v5 38/39] mm: Add large page readahead
Date: Thu, 28 May 2020 19:58:23 -0700	[thread overview]
Message-ID: <20200529025824.32296-39-willy@infradead.org> (raw)
In-Reply-To: <20200529025824.32296-1-willy@infradead.org>

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

If the filesystem supports large pages, allocate larger pages in the
readahead code when it seems worth doing.  The heuristic for choosing
larger page sizes will surely need some tuning, but this aggressive
ramp-up seems good for testing.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 mm/readahead.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 87 insertions(+), 6 deletions(-)

diff --git a/mm/readahead.c b/mm/readahead.c
index 74c7e1eff540..ac16e96a8828 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -149,7 +149,7 @@ static void read_pages(struct readahead_control *rac, struct list_head *pages,
 
 	blk_finish_plug(&plug);
 
-	BUG_ON(!list_empty(pages));
+	BUG_ON(pages && !list_empty(pages));
 	BUG_ON(readahead_count(rac));
 
 out:
@@ -428,13 +428,92 @@ static int try_context_readahead(struct address_space *mapping,
 	return 1;
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline int ra_alloc_page(struct readahead_control *rac, pgoff_t index,
+		pgoff_t mark, unsigned int order, gfp_t gfp)
+{
+	int err;
+	struct page *page = __page_cache_alloc_order(gfp, order);
+
+	if (!page)
+		return -ENOMEM;
+	if (mark - index < (1UL << order))
+		SetPageReadahead(page);
+	err = add_to_page_cache_lru(page, rac->mapping, index, gfp);
+	if (err)
+		put_page(page);
+	else
+		rac->_nr_pages += 1UL << order;
+	return err;
+}
+
+static bool page_cache_readahead_order(struct readahead_control *rac,
+		struct file_ra_state *ra, unsigned int order)
+{
+	struct address_space *mapping = rac->mapping;
+	unsigned int old_order = order;
+	pgoff_t index = readahead_index(rac);
+	pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT;
+	pgoff_t mark = index + ra->size - ra->async_size;
+	int err = 0;
+	gfp_t gfp = readahead_gfp_mask(mapping);
+
+	if (!mapping_large_pages(mapping))
+		return false;
+
+	limit = min(limit, index + ra->size - 1);
+
+	/* Grow page size up to PMD size */
+	if (order < HPAGE_PMD_ORDER) {
+		order += 2;
+		if (order > HPAGE_PMD_ORDER)
+			order = HPAGE_PMD_ORDER;
+		while ((1 << order) > ra->size)
+			order--;
+	}
+
+	/* If size is somehow misaligned, fill with order-0 pages */
+	while (!err && index & ((1UL << old_order) - 1))
+		err = ra_alloc_page(rac, index++, mark, 0, gfp);
+
+	while (!err && index & ((1UL << order) - 1)) {
+		err = ra_alloc_page(rac, index, mark, old_order, gfp);
+		index += 1UL << old_order;
+	}
+
+	while (!err && index <= limit) {
+		err = ra_alloc_page(rac, index, mark, order, gfp);
+		index += 1UL << order;
+	}
+
+	if (index > limit) {
+		ra->size += index - limit - 1;
+		ra->async_size += index - limit - 1;
+	}
+
+	read_pages(rac, NULL, false);
+
+	/*
+	 * If there were already pages in the page cache, then we may have
+	 * left some gaps.  Let the regular readahead code take care of this
+	 * situation.
+	 */
+	return !err;
+}
+#else
+static bool page_cache_readahead_order(struct readahead_control *rac,
+		struct file_ra_state *ra, unsigned int order)
+{
+	return false;
+}
+#endif
+
 /*
  * A minimal readahead algorithm for trivial sequential/random reads.
  */
 static void ondemand_readahead(struct address_space *mapping,
 		struct file_ra_state *ra, struct file *file,
-		bool hit_readahead_marker, pgoff_t index,
-		unsigned long req_size)
+		struct page *page, pgoff_t index, unsigned long req_size)
 {
 	DEFINE_READAHEAD(rac, file, mapping, index);
 	struct backing_dev_info *bdi = inode_to_bdi(mapping->host);
@@ -473,7 +552,7 @@ static void ondemand_readahead(struct address_space *mapping,
 	 * Query the pagecache for async_size, which normally equals to
 	 * readahead size. Ramp it up and use it as the new readahead size.
 	 */
-	if (hit_readahead_marker) {
+	if (page) {
 		pgoff_t start;
 
 		rcu_read_lock();
@@ -544,6 +623,8 @@ static void ondemand_readahead(struct address_space *mapping,
 	}
 
 	rac._index = ra->start;
+	if (page && page_cache_readahead_order(&rac, ra, compound_order(page)))
+		return;
 	__do_page_cache_readahead(&rac, ra->size, ra->async_size);
 }
 
@@ -578,7 +659,7 @@ void page_cache_sync_readahead(struct address_space *mapping,
 	}
 
 	/* do read-ahead */
-	ondemand_readahead(mapping, ra, filp, false, index, req_count);
+	ondemand_readahead(mapping, ra, filp, NULL, index, req_count);
 }
 EXPORT_SYMBOL_GPL(page_cache_sync_readahead);
 
@@ -624,7 +705,7 @@ page_cache_async_readahead(struct address_space *mapping,
 		return;
 
 	/* do read-ahead */
-	ondemand_readahead(mapping, ra, filp, true, index, req_count);
+	ondemand_readahead(mapping, ra, filp, page, index, req_count);
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
 
-- 
2.26.2



  parent reply	other threads:[~2020-05-29  2:59 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-29  2:57 [PATCH v5 00/39] Large pages in the page cache Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 01/39] mm: Move PageDoubleMap bit Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 02/39] mm: Simplify PageDoubleMap with PF_SECOND policy Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 03/39] mm: Allow hpages to be arbitrary order Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 04/39] mm: Introduce thp_size Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 05/39] mm: Introduce thp_order Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 06/39] mm: Introduce offset_in_thp Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 07/39] fs: Add a filesystem flag for large pages Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 08/39] fs: Do not update nr_thps for large page mappings Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 09/39] fs: Introduce i_blocks_per_page Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 10/39] fs: Make page_mkwrite_check_truncate thp-aware Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 11/39] fs: Support THPs in zero_user_segments Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 12/39] bio: Add bio_for_each_thp_segment_all Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 13/39] iomap: Support arbitrarily many blocks per page Matthew Wilcox
2020-05-29  2:57 ` [PATCH v5 14/39] iomap: Support large pages in iomap_adjust_read_range Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 15/39] iomap: Support large pages in invalidatepage Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 16/39] iomap: Support large pages in read paths Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 17/39] iomap: Support large pages in write paths Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 18/39] iomap: Inline data shouldn't see large pages Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 19/39] iomap: Handle tail pages in iomap_page_mkwrite Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 20/39] xfs: Support large pages Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 21/39] mm: Make prep_transhuge_page return its argument Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 22/39] mm: Add __page_cache_alloc_order Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 23/39] mm: Allow large pages to be added to the page cache Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 24/39] mm: Allow large pages to be removed from " Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 25/39] mm: Remove page fault assumption of compound page size Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 26/39] mm: Fix total_mapcount assumption of " Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 27/39] mm: Remove assumptions of THP size Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 28/39] mm: Avoid splitting large pages Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 29/39] mm: Fix truncation for pages of arbitrary size Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 30/39] mm: Handle truncates that split large pages Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 31/39] mm: Support storing shadow entries for " Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 32/39] mm: Support retrieving tail pages from the page cache Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 33/39] mm: Support tail pages in wait_for_stable_page Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 34/39] mm: Add DEFINE_READAHEAD Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 35/39] mm: Make page_cache_readahead_unbounded take a readahead_control Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 36/39] mm: Make __do_page_cache_readahead " Matthew Wilcox
2020-05-29  2:58 ` [PATCH v5 37/39] mm: Allow PageReadahead to be set on head pages Matthew Wilcox
2020-05-29  2:58 ` Matthew Wilcox [this message]
2020-05-29  2:58 ` [PATCH v5 39/39] mm: Align THP mappings for non-DAX Matthew Wilcox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200529025824.32296-39-willy@infradead.org \
    --to=willy@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).