Skip to content

Commit a8cf7f2

Browse files
Matthew Wilcox (Oracle)torvalds
authored andcommitted
mm: add find_lock_head
Add a new FGP_HEAD flag which avoids calling find_subpage() and add a convenience wrapper for it. 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-9-willy@infradead.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 63ec197 commit a8cf7f2

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

include/linux/pagemap.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ pgoff_t page_cache_prev_miss(struct address_space *mapping,
279279
#define FGP_NOFS 0x00000010
280280
#define FGP_NOWAIT 0x00000020
281281
#define FGP_FOR_MMAP 0x00000040
282+
#define FGP_HEAD 0x00000080
282283

283284
struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset,
284285
int fgp_flags, gfp_t cache_gfp_mask);
@@ -310,18 +311,37 @@ static inline struct page *find_get_page_flags(struct address_space *mapping,
310311
* @mapping: the address_space to search
311312
* @offset: the page index
312313
*
313-
* Looks up the page cache slot at @mapping & @offset. If there is a
314+
* Looks up the page cache entry at @mapping & @offset. If there is a
314315
* page cache page, it is returned locked and with an increased
315316
* refcount.
316317
*
317-
* Otherwise, %NULL is returned.
318-
*
319-
* find_lock_page() may sleep.
318+
* Context: May sleep.
319+
* Return: A struct page or %NULL if there is no page in the cache for this
320+
* index.
320321
*/
321322
static inline struct page *find_lock_page(struct address_space *mapping,
322-
pgoff_t offset)
323+
pgoff_t index)
324+
{
325+
return pagecache_get_page(mapping, index, FGP_LOCK, 0);
326+
}
327+
328+
/**
329+
* find_lock_head - Locate, pin and lock a pagecache page.
330+
* @mapping: The address_space to search.
331+
* @offset: The page index.
332+
*
333+
* Looks up the page cache entry at @mapping & @offset. If there is a
334+
* page cache page, its head page is returned locked and with an increased
335+
* refcount.
336+
*
337+
* Context: May sleep.
338+
* Return: A struct page which is !PageTail, or %NULL if there is no page
339+
* in the cache for this index.
340+
*/
341+
static inline struct page *find_lock_head(struct address_space *mapping,
342+
pgoff_t index)
323343
{
324-
return pagecache_get_page(mapping, offset, FGP_LOCK, 0);
344+
return pagecache_get_page(mapping, index, FGP_LOCK | FGP_HEAD, 0);
325345
}
326346

327347
/**

mm/filemap.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,8 @@ struct page *find_lock_entry(struct address_space *mapping, pgoff_t index)
17371737
*
17381738
* * %FGP_ACCESSED - The page will be marked accessed.
17391739
* * %FGP_LOCK - The page is returned locked.
1740+
* * %FGP_HEAD - If the page is present and a THP, return the head page
1741+
* rather than the exact page specified by the index.
17401742
* * %FGP_CREAT - If no page is present then a new page is allocated using
17411743
* @gfp_mask and added to the page cache and the VM's LRU list.
17421744
* The page is returned locked and with an increased refcount.
@@ -1765,7 +1767,6 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
17651767
page = NULL;
17661768
if (!page)
17671769
goto no_page;
1768-
page = find_subpage(page, index);
17691770

17701771
if (fgp_flags & FGP_LOCK) {
17711772
if (fgp_flags & FGP_NOWAIT) {
@@ -1778,12 +1779,12 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
17781779
}
17791780

17801781
/* Has the page been truncated? */
1781-
if (unlikely(compound_head(page)->mapping != mapping)) {
1782+
if (unlikely(page->mapping != mapping)) {
17821783
unlock_page(page);
17831784
put_page(page);
17841785
goto repeat;
17851786
}
1786-
VM_BUG_ON_PAGE(page->index != index, page);
1787+
VM_BUG_ON_PAGE(!thp_contains(page, index), page);
17871788
}
17881789

17891790
if (fgp_flags & FGP_ACCESSED)
@@ -1793,6 +1794,8 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t index,
17931794
if (page_is_idle(page))
17941795
clear_page_idle(page);
17951796
}
1797+
if (!(fgp_flags & FGP_HEAD))
1798+
page = find_subpage(page, index);
17961799

17971800
no_page:
17981801
if (!page && (fgp_flags & FGP_CREAT)) {

0 commit comments

Comments
 (0)