Commit b1d0ec3a authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Andrew Morton

mm/shmem: convert shmem_getpage_gfp to use a folio

Rename shmem_alloc_and_acct_page() to shmem_alloc_and_acct_folio() and
have it return a folio, then use a folio throuughout shmem_getpage_gfp(). 
It continues to return a struct page.

Link: https://lkml.kernel.org/r/20220504182857.4013401-23-willy@infradead.orgSigned-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 72827e5c
......@@ -1563,8 +1563,7 @@ static struct page *shmem_alloc_page(gfp_t gfp,
return &shmem_alloc_folio(gfp, info, index)->page;
}
static struct page *shmem_alloc_and_acct_page(gfp_t gfp,
struct inode *inode,
static struct folio *shmem_alloc_and_acct_folio(gfp_t gfp, struct inode *inode,
pgoff_t index, bool huge)
{
struct shmem_inode_info *info = SHMEM_I(inode);
......@@ -1586,7 +1585,7 @@ static struct page *shmem_alloc_and_acct_page(gfp_t gfp,
if (folio) {
__folio_set_locked(folio);
__folio_set_swapbacked(folio);
return &folio->page;
return folio;
}
err = -ENOMEM;
......@@ -1800,7 +1799,6 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
struct shmem_sb_info *sbinfo;
struct mm_struct *charge_mm;
struct folio *folio;
struct page *page;
pgoff_t hindex = index;
gfp_t huge_gfp;
int error;
......@@ -1818,19 +1816,18 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
sbinfo = SHMEM_SB(inode->i_sb);
charge_mm = vma ? vma->vm_mm : NULL;
page = pagecache_get_page(mapping, index,
FGP_ENTRY | FGP_HEAD | FGP_LOCK, 0);
if (page && vma && userfaultfd_minor(vma)) {
if (!xa_is_value(page)) {
unlock_page(page);
put_page(page);
folio = __filemap_get_folio(mapping, index, FGP_ENTRY | FGP_LOCK, 0);
if (folio && vma && userfaultfd_minor(vma)) {
if (!xa_is_value(folio)) {
folio_unlock(folio);
folio_put(folio);
}
*fault_type = handle_userfault(vmf, VM_UFFD_MINOR);
return 0;
}
if (xa_is_value(page)) {
if (xa_is_value(folio)) {
struct page *page = &folio->page;
error = shmem_swapin_page(inode, index, &page,
sgp, gfp, vma, fault_type);
if (error == -EEXIST)
......@@ -1840,17 +1837,17 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
return error;
}
if (page) {
hindex = page->index;
if (folio) {
hindex = folio->index;
if (sgp == SGP_WRITE)
mark_page_accessed(page);
if (PageUptodate(page))
folio_mark_accessed(folio);
if (folio_test_uptodate(folio))
goto out;
/* fallocated page */
if (sgp != SGP_READ)
goto clear;
unlock_page(page);
put_page(page);
folio_unlock(folio);
folio_put(folio);
}
/*
......@@ -1877,17 +1874,16 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
huge_gfp = vma_thp_gfp_mask(vma);
huge_gfp = limit_gfp_mask(huge_gfp, gfp);
page = shmem_alloc_and_acct_page(huge_gfp, inode, index, true);
if (IS_ERR(page)) {
folio = shmem_alloc_and_acct_folio(huge_gfp, inode, index, true);
if (IS_ERR(folio)) {
alloc_nohuge:
page = shmem_alloc_and_acct_page(gfp, inode,
index, false);
folio = shmem_alloc_and_acct_folio(gfp, inode, index, false);
}
if (IS_ERR(page)) {
if (IS_ERR(folio)) {
int retry = 5;
error = PTR_ERR(page);
page = NULL;
error = PTR_ERR(folio);
folio = NULL;
if (error != -ENOSPC)
goto unlock;
/*
......@@ -1906,30 +1902,26 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
goto unlock;
}
if (PageTransHuge(page))
hindex = round_down(index, HPAGE_PMD_NR);
else
hindex = index;
hindex = round_down(index, folio_nr_pages(folio));
if (sgp == SGP_WRITE)
__SetPageReferenced(page);
__folio_set_referenced(folio);
folio = page_folio(page);
error = shmem_add_to_page_cache(folio, mapping, hindex,
NULL, gfp & GFP_RECLAIM_MASK,
charge_mm);
if (error)
goto unacct;
lru_cache_add(page);
folio_add_lru(folio);
spin_lock_irq(&info->lock);
info->alloced += compound_nr(page);
inode->i_blocks += BLOCKS_PER_PAGE << compound_order(page);
info->alloced += folio_nr_pages(folio);
inode->i_blocks += BLOCKS_PER_PAGE << folio_order(folio);
shmem_recalc_inode(inode);
spin_unlock_irq(&info->lock);
alloced = true;
if (PageTransHuge(page) &&
if (folio_test_pmd_mappable(folio) &&
DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE) <
hindex + HPAGE_PMD_NR - 1) {
/*
......@@ -1960,22 +1952,21 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
* but SGP_FALLOC on a page fallocated earlier must initialize
* it now, lest undo on failure cancel our earlier guarantee.
*/
if (sgp != SGP_WRITE && !PageUptodate(page)) {
int i;
if (sgp != SGP_WRITE && !folio_test_uptodate(folio)) {
long i, n = folio_nr_pages(folio);
for (i = 0; i < compound_nr(page); i++) {
clear_highpage(page + i);
flush_dcache_page(page + i);
}
SetPageUptodate(page);
for (i = 0; i < n; i++)
clear_highpage(folio_page(folio, i));
flush_dcache_folio(folio);
folio_mark_uptodate(folio);
}
/* Perhaps the file has been truncated since we checked */
if (sgp <= SGP_CACHE &&
((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) {
if (alloced) {
ClearPageDirty(page);
delete_from_page_cache(page);
folio_clear_dirty(folio);
filemap_remove_folio(folio);
spin_lock_irq(&info->lock);
shmem_recalc_inode(inode);
spin_unlock_irq(&info->lock);
......@@ -1984,24 +1975,24 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
goto unlock;
}
out:
*pagep = page + index - hindex;
*pagep = folio_page(folio, index - hindex);
return 0;
/*
* Error recovery.
*/
unacct:
shmem_inode_unacct_blocks(inode, compound_nr(page));
shmem_inode_unacct_blocks(inode, folio_nr_pages(folio));
if (PageTransHuge(page)) {
unlock_page(page);
put_page(page);
if (folio_test_large(folio)) {
folio_unlock(folio);
folio_put(folio);
goto alloc_nohuge;
}
unlock:
if (page) {
unlock_page(page);
put_page(page);
if (folio) {
folio_unlock(folio);
folio_put(folio);
}
if (error == -ENOSPC && !once++) {
spin_lock_irq(&info->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment