Skip to content

Commit 63ec197

Browse files
Matthew Wilcox (Oracle)torvalds
authored andcommitted
mm/shmem: return head page from find_lock_entry
Convert shmem_getpage_gfp() (the only remaining caller of find_lock_entry()) to cope with a head page being returned instead of the subpage for the index. [willy@infradead.org: fix BUG()s] Link https://lore.kernel.org/linux-mm/20200912032042.GA6583@casper.infradead.org/ Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Huang Ying <ying.huang@intel.com> Cc: Hugh Dickins <hughd@google.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Matthew Auld <matthew.auld@intel.com> Cc: William Kucharski <william.kucharski@oracle.com> Link: https://lkml.kernel.org/r/20200910183318.20139-8-willy@infradead.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent a6de4b4 commit 63ec197

File tree

3 files changed

+30
-23
lines changed

3 files changed

+30
-23
lines changed

include/linux/pagemap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,15 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping,
372372
mapping_gfp_mask(mapping));
373373
}
374374

375+
/* Does this page contain this index? */
376+
static inline bool thp_contains(struct page *head, pgoff_t index)
377+
{
378+
/* HugeTLBfs indexes the page cache in units of hpage_size */
379+
if (PageHuge(head))
380+
return head->index == index;
381+
return page_index(head) == (index & ~(thp_nr_pages(head) - 1UL));
382+
}
383+
375384
/*
376385
* Given the page we found in the page cache, return the page corresponding
377386
* to this index in the file

mm/filemap.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,37 +1692,34 @@ struct page *find_get_entry(struct address_space *mapping, pgoff_t index)
16921692
}
16931693

16941694
/**
1695-
* find_lock_entry - locate, pin and lock a page cache entry
1696-
* @mapping: the address_space to search
1697-
* @offset: the page cache index
1695+
* find_lock_entry - Locate and lock a page cache entry.
1696+
* @mapping: The address_space to search.
1697+
* @index: The page cache index.
16981698
*
1699-
* Looks up the page cache slot at @mapping & @offset. If there is a
1700-
* page cache page, it is returned locked and with an increased
1701-
* refcount.
1699+
* Looks up the page at @mapping & @index. If there is a page in the
1700+
* cache, the head page is returned locked and with an increased refcount.
17021701
*
17031702
* If the slot holds a shadow entry of a previously evicted page, or a
17041703
* swap entry from shmem/tmpfs, it is returned.
17051704
*
1706-
* find_lock_entry() may sleep.
1707-
*
1708-
* Return: the found page or shadow entry, %NULL if nothing is found.
1705+
* Context: May sleep.
1706+
* Return: The head page or shadow entry, %NULL if nothing is found.
17091707
*/
1710-
struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset)
1708+
struct page *find_lock_entry(struct address_space *mapping, pgoff_t index)
17111709
{
17121710
struct page *page;
17131711

17141712
repeat:
1715-
page = find_get_entry(mapping, offset);
1713+
page = find_get_entry(mapping, index);
17161714
if (page && !xa_is_value(page)) {
17171715
lock_page(page);
17181716
/* Has the page been truncated? */
1719-
if (unlikely(page_mapping(page) != mapping)) {
1717+
if (unlikely(page->mapping != mapping)) {
17201718
unlock_page(page);
17211719
put_page(page);
17221720
goto repeat;
17231721
}
1724-
page = find_subpage(page, offset);
1725-
VM_BUG_ON_PAGE(page_to_pgoff(page) != offset, page);
1722+
VM_BUG_ON_PAGE(!thp_contains(page, index), page);
17261723
}
17271724
return page;
17281725
}

mm/shmem.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,8 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
18301830
return error;
18311831
}
18321832

1833+
if (page)
1834+
hindex = page->index;
18331835
if (page && sgp == SGP_WRITE)
18341836
mark_page_accessed(page);
18351837

@@ -1840,11 +1842,10 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
18401842
unlock_page(page);
18411843
put_page(page);
18421844
page = NULL;
1845+
hindex = index;
18431846
}
1844-
if (page || sgp == SGP_READ) {
1845-
*pagep = page;
1846-
return 0;
1847-
}
1847+
if (page || sgp == SGP_READ)
1848+
goto out;
18481849

18491850
/*
18501851
* Fast cache lookup did not find it:
@@ -1969,14 +1970,13 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
19691970
* it now, lest undo on failure cancel our earlier guarantee.
19701971
*/
19711972
if (sgp != SGP_WRITE && !PageUptodate(page)) {
1972-
struct page *head = compound_head(page);
19731973
int i;
19741974

1975-
for (i = 0; i < compound_nr(head); i++) {
1976-
clear_highpage(head + i);
1977-
flush_dcache_page(head + i);
1975+
for (i = 0; i < compound_nr(page); i++) {
1976+
clear_highpage(page + i);
1977+
flush_dcache_page(page + i);
19781978
}
1979-
SetPageUptodate(head);
1979+
SetPageUptodate(page);
19801980
}
19811981

19821982
/* Perhaps the file has been truncated since we checked */
@@ -1992,6 +1992,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
19921992
error = -EINVAL;
19931993
goto unlock;
19941994
}
1995+
out:
19951996
*pagep = page + index - hindex;
19961997
return 0;
19971998

0 commit comments

Comments
 (0)