Commit 16e4bce6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pagecache fixes from Matthew Wilcox:
 "Four folio-related fixes for 5.19:

   - Mark a folio accessed at the right time (Yu Kuai)

   - Fix a race for folios being replaced in the middle of a read (Brian
     Foster)

   - Clear folio->private in more places (Xiubo Li)

   - Take the invalidate_lock in page_cache_ra_order() (Alistair Popple)"

* tag 'folio-5.19b' of git://git.infradead.org/users/willy/pagecache:
  filemap: Fix serialization adding transparent huge pages to page cache
  mm: Clear page->private when splitting or migrating a page
  filemap: Handle sibling entries in filemap_get_read_batch()
  filemap: Correct the conditions for marking a folio as accessed
parents 599d1691 00fa15e0
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -2385,6 +2385,8 @@ static void filemap_get_read_batch(struct address_space *mapping,
			continue;
		if (xas.xa_index > max || xa_is_value(folio))
			break;
		if (xa_is_sibling(folio))
			break;
		if (!folio_try_get_rcu(folio))
			goto retry;

@@ -2629,6 +2631,13 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter,
	return err;
}

static inline bool pos_same_folio(loff_t pos1, loff_t pos2, struct folio *folio)
{
	unsigned int shift = folio_shift(folio);

	return (pos1 >> shift == pos2 >> shift);
}

/**
 * filemap_read - Read data from the page cache.
 * @iocb: The iocb to read.
@@ -2700,11 +2709,11 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
		writably_mapped = mapping_writably_mapped(mapping);

		/*
		 * When a sequential read accesses a page several times, only
		 * When a read accesses the same folio several times, only
		 * mark it as accessed the first time.
		 */
		if (iocb->ki_pos >> PAGE_SHIFT !=
		    ra->prev_pos >> PAGE_SHIFT)
		if (!pos_same_folio(iocb->ki_pos, ra->prev_pos - 1,
							fbatch.folios[0]))
			folio_mark_accessed(fbatch.folios[0]);

		for (i = 0; i < folio_batch_count(&fbatch); i++) {
+1 −0
Original line number Diff line number Diff line
@@ -2377,6 +2377,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
			page_tail);
	page_tail->mapping = head->mapping;
	page_tail->index = head->index + tail;
	page_tail->private = 0;

	/* Page flags must be visible before we make the page non-compound. */
	smp_wmb();
+1 −0
Original line number Diff line number Diff line
@@ -1106,6 +1106,7 @@ static int unmap_and_move(new_page_t get_new_page,
	if (!newpage)
		return -ENOMEM;

	newpage->private = 0;
	rc = __unmap_and_move(page, newpage, force, mode);
	if (rc == MIGRATEPAGE_SUCCESS)
		set_page_owner_migrate_reason(newpage, reason);
+2 −0
Original line number Diff line number Diff line
@@ -510,6 +510,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
			new_order--;
	}

	filemap_invalidate_lock_shared(mapping);
	while (index <= limit) {
		unsigned int order = new_order;

@@ -536,6 +537,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
	}

	read_pages(ractl);
	filemap_invalidate_unlock_shared(mapping);

	/*
	 * If there were already pages in the page cache, then we may have