]> git.ipfire.org Git - thirdparty/kernel/stable.git/blobdiff - mm/shmem.c
mm: khugepaged: introduce khugepaged_enter_vma() helper
[thirdparty/kernel/stable.git] / mm / shmem.c
index 4b2fea33158e8a33a87354ccefc574ef74c1e793..89f6f4fec3f9a0a472e1db3269ee2cd6d0c53181 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/hugetlb.h>
 #include <linux/fs_parser.h>
 #include <linux/swapfile.h>
+#include "swap.h"
 
 static struct vfsmount *shm_mnt;
 
@@ -134,8 +135,8 @@ static unsigned long shmem_default_max_inodes(void)
 }
 #endif
 
-static int shmem_swapin_page(struct inode *inode, pgoff_t index,
-                            struct page **pagep, enum sgp_type sgp,
+static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
+                            struct folio **foliop, enum sgp_type sgp,
                             gfp_t gfp, struct vm_area_struct *vma,
                             vm_fault_t *fault_type);
 static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
@@ -553,7 +554,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
        LIST_HEAD(to_remove);
        struct inode *inode;
        struct shmem_inode_info *info;
-       struct page *page;
+       struct folio *folio;
        unsigned long batch = sc ? sc->nr_to_scan : 128;
        int split = 0;
 
@@ -597,6 +598,7 @@ next:
 
        list_for_each_safe(pos, next, &list) {
                int ret;
+               pgoff_t index;
 
                info = list_entry(pos, struct shmem_inode_info, shrinklist);
                inode = &info->vfs_inode;
@@ -604,14 +606,14 @@ next:
                if (nr_to_split && split >= nr_to_split)
                        goto move_back;
 
-               page = find_get_page(inode->i_mapping,
-                               (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
-               if (!page)
+               index = (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT;
+               folio = filemap_get_folio(inode->i_mapping, index);
+               if (!folio)
                        goto drop;
 
                /* No huge page at the end of the file: nothing to split */
-               if (!PageTransHuge(page)) {
-                       put_page(page);
+               if (!folio_test_large(folio)) {
+                       folio_put(folio);
                        goto drop;
                }
 
@@ -622,14 +624,14 @@ next:
                 * Waiting for the lock may lead to deadlock in the
                 * reclaim path.
                 */
-               if (!trylock_page(page)) {
-                       put_page(page);
+               if (!folio_trylock(folio)) {
+                       folio_put(folio);
                        goto move_back;
                }
 
-               ret = split_huge_page(page);
-               unlock_page(page);
-               put_page(page);
+               ret = split_huge_page(&folio->page);
+               folio_unlock(folio);
+               folio_put(folio);
 
                /* If split failed move the inode on the list back to shrinklist */
                if (ret)
@@ -694,36 +696,35 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
 /*
  * Like add_to_page_cache_locked, but error if expected item has gone.
  */
-static int shmem_add_to_page_cache(struct page *page,
+static int shmem_add_to_page_cache(struct folio *folio,
                                   struct address_space *mapping,
                                   pgoff_t index, void *expected, gfp_t gfp,
                                   struct mm_struct *charge_mm)
 {
-       XA_STATE_ORDER(xas, &mapping->i_pages, index, compound_order(page));
-       unsigned long nr = compound_nr(page);
+       XA_STATE_ORDER(xas, &mapping->i_pages, index, folio_order(folio));
+       long nr = folio_nr_pages(folio);
        int error;
 
-       VM_BUG_ON_PAGE(PageTail(page), page);
-       VM_BUG_ON_PAGE(index != round_down(index, nr), page);
-       VM_BUG_ON_PAGE(!PageLocked(page), page);
-       VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
-       VM_BUG_ON(expected && PageTransHuge(page));
+       VM_BUG_ON_FOLIO(index != round_down(index, nr), folio);
+       VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
+       VM_BUG_ON_FOLIO(!folio_test_swapbacked(folio), folio);
+       VM_BUG_ON(expected && folio_test_large(folio));
 
-       page_ref_add(page, nr);
-       page->mapping = mapping;
-       page->index = index;
+       folio_ref_add(folio, nr);
+       folio->mapping = mapping;
+       folio->index = index;
 
-       if (!PageSwapCache(page)) {
-               error = mem_cgroup_charge(page_folio(page), charge_mm, gfp);
+       if (!folio_test_swapcache(folio)) {
+               error = mem_cgroup_charge(folio, charge_mm, gfp);
                if (error) {
-                       if (PageTransHuge(page)) {
+                       if (folio_test_pmd_mappable(folio)) {
                                count_vm_event(THP_FILE_FALLBACK);
                                count_vm_event(THP_FILE_FALLBACK_CHARGE);
                        }
                        goto error;
                }
        }
-       cgroup_throttle_swaprate(page, gfp);
+       folio_throttle_swaprate(folio, gfp);
 
        do {
                xas_lock_irq(&xas);
@@ -735,16 +736,16 @@ static int shmem_add_to_page_cache(struct page *page,
                        xas_set_err(&xas, -EEXIST);
                        goto unlock;
                }
-               xas_store(&xas, page);
+               xas_store(&xas, folio);
                if (xas_error(&xas))
                        goto unlock;
-               if (PageTransHuge(page)) {
+               if (folio_test_pmd_mappable(folio)) {
                        count_vm_event(THP_FILE_ALLOC);
-                       __mod_lruvec_page_state(page, NR_SHMEM_THPS, nr);
+                       __lruvec_stat_mod_folio(folio, NR_SHMEM_THPS, nr);
                }
                mapping->nrpages += nr;
-               __mod_lruvec_page_state(page, NR_FILE_PAGES, nr);
-               __mod_lruvec_page_state(page, NR_SHMEM, nr);
+               __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, nr);
+               __lruvec_stat_mod_folio(folio, NR_SHMEM, nr);
 unlock:
                xas_unlock_irq(&xas);
        } while (xas_nomem(&xas, gfp));
@@ -756,8 +757,8 @@ unlock:
 
        return 0;
 error:
-       page->mapping = NULL;
-       page_ref_sub(page, nr);
+       folio->mapping = NULL;
+       folio_ref_sub(folio, nr);
        return error;
 }
 
@@ -1158,69 +1159,64 @@ static void shmem_evict_inode(struct inode *inode)
 }
 
 static int shmem_find_swap_entries(struct address_space *mapping,
-                                  pgoff_t start, unsigned int nr_entries,
-                                  struct page **entries, pgoff_t *indices,
-                                  unsigned int type)
+                                  pgoff_t start, struct folio_batch *fbatch,
+                                  pgoff_t *indices, unsigned int type)
 {
        XA_STATE(xas, &mapping->i_pages, start);
-       struct page *page;
+       struct folio *folio;
        swp_entry_t entry;
        unsigned int ret = 0;
 
-       if (!nr_entries)
-               return 0;
-
        rcu_read_lock();
-       xas_for_each(&xas, page, ULONG_MAX) {
-               if (xas_retry(&xas, page))
+       xas_for_each(&xas, folio, ULONG_MAX) {
+               if (xas_retry(&xas, folio))
                        continue;
 
-               if (!xa_is_value(page))
+               if (!xa_is_value(folio))
                        continue;
 
-               entry = radix_to_swp_entry(page);
+               entry = radix_to_swp_entry(folio);
                if (swp_type(entry) != type)
                        continue;
 
                indices[ret] = xas.xa_index;
-               entries[ret] = page;
+               if (!folio_batch_add(fbatch, folio))
+                       break;
 
                if (need_resched()) {
                        xas_pause(&xas);
                        cond_resched_rcu();
                }
-               if (++ret == nr_entries)
-                       break;
        }
        rcu_read_unlock();
 
-       return ret;
+       return xas.xa_index;
 }
 
 /*
  * Move the swapped pages for an inode to page cache. Returns the count
  * of pages swapped in, or the error in case of failure.
  */
-static int shmem_unuse_swap_entries(struct inode *inode, struct pagevec pvec,
-                                   pgoff_t *indices)
+static int shmem_unuse_swap_entries(struct inode *inode,
+               struct folio_batch *fbatch, pgoff_t *indices)
 {
        int i = 0;
        int ret = 0;
        int error = 0;
        struct address_space *mapping = inode->i_mapping;
 
-       for (i = 0; i < pvec.nr; i++) {
-               struct page *page = pvec.pages[i];
+       for (i = 0; i < folio_batch_count(fbatch); i++) {
+               struct folio *folio = fbatch->folios[i];
 
-               if (!xa_is_value(page))
+               if (!xa_is_value(folio))
                        continue;
-               error = shmem_swapin_page(inode, indices[i],
-                                         &page, SGP_CACHE,
+               error = shmem_swapin_folio(inode, indices[i],
+                                         &folio, SGP_CACHE,
                                          mapping_gfp_mask(mapping),
                                          NULL, NULL);
                if (error == 0) {
-                       unlock_page(page);
-                       put_page(page);
+                       folio_unlock(folio);
+                       folio_put(folio);
                        ret++;
                }
                if (error == -ENOMEM)
@@ -1237,26 +1233,23 @@ static int shmem_unuse_inode(struct inode *inode, unsigned int type)
 {
        struct address_space *mapping = inode->i_mapping;
        pgoff_t start = 0;
-       struct pagevec pvec;
+       struct folio_batch fbatch;
        pgoff_t indices[PAGEVEC_SIZE];
        int ret = 0;
 
-       pagevec_init(&pvec);
        do {
-               unsigned int nr_entries = PAGEVEC_SIZE;
-
-               pvec.nr = shmem_find_swap_entries(mapping, start, nr_entries,
-                                                 pvec.pages, indices, type);
-               if (pvec.nr == 0) {
+               folio_batch_init(&fbatch);
+               shmem_find_swap_entries(mapping, start, &fbatch, indices, type);
+               if (folio_batch_count(&fbatch) == 0) {
                        ret = 0;
                        break;
                }
 
-               ret = shmem_unuse_swap_entries(inode, pvec, indices);
+               ret = shmem_unuse_swap_entries(inode, &fbatch, indices);
                if (ret < 0)
                        break;
 
-               start = indices[pvec.nr - 1];
+               start = indices[folio_batch_count(&fbatch) - 1];
        } while (true);
 
        return ret;
@@ -1312,6 +1305,7 @@ int shmem_unuse(unsigned int type)
  */
 static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 {
+       struct folio *folio = page_folio(page);
        struct shmem_inode_info *info;
        struct address_space *mapping;
        struct inode *inode;
@@ -1385,7 +1379,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
                SetPageUptodate(page);
        }
 
-       swap = get_swap_page(page);
+       swap = folio_alloc_swap(folio);
        if (!swap.val)
                goto redirty;
 
@@ -1521,13 +1515,13 @@ static gfp_t limit_gfp_mask(gfp_t huge_gfp, gfp_t limit_gfp)
        return result;
 }
 
-static struct page *shmem_alloc_hugepage(gfp_t gfp,
+static struct folio *shmem_alloc_hugefolio(gfp_t gfp,
                struct shmem_inode_info *info, pgoff_t index)
 {
        struct vm_area_struct pvma;
        struct address_space *mapping = info->vfs_inode.i_mapping;
        pgoff_t hindex;
-       struct page *page;
+       struct folio *folio;
 
        hindex = round_down(index, HPAGE_PMD_NR);
        if (xa_find(&mapping->i_pages, &hindex, hindex + HPAGE_PMD_NR - 1,
@@ -1535,34 +1529,37 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
                return NULL;
 
        shmem_pseudo_vma_init(&pvma, info, hindex);
-       page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, &pvma, 0, true);
+       folio = vma_alloc_folio(gfp, HPAGE_PMD_ORDER, &pvma, 0, true);
        shmem_pseudo_vma_destroy(&pvma);
-       if (page)
-               prep_transhuge_page(page);
-       else
+       if (!folio)
                count_vm_event(THP_FILE_FALLBACK);
-       return page;
+       return folio;
 }
 
-static struct page *shmem_alloc_page(gfp_t gfp,
+static struct folio *shmem_alloc_folio(gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
 {
        struct vm_area_struct pvma;
-       struct page *page;
+       struct folio *folio;
 
        shmem_pseudo_vma_init(&pvma, info, index);
-       page = alloc_page_vma(gfp, &pvma, 0);
+       folio = vma_alloc_folio(gfp, 0, &pvma, 0, false);
        shmem_pseudo_vma_destroy(&pvma);
 
-       return page;
+       return folio;
+}
+
+static struct page *shmem_alloc_page(gfp_t gfp,
+                       struct shmem_inode_info *info, pgoff_t index)
+{
+       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);
-       struct page *page;
+       struct folio *folio;
        int nr;
        int err = -ENOSPC;
 
@@ -1574,13 +1571,13 @@ static struct page *shmem_alloc_and_acct_page(gfp_t gfp,
                goto failed;
 
        if (huge)
-               page = shmem_alloc_hugepage(gfp, info, index);
+               folio = shmem_alloc_hugefolio(gfp, info, index);
        else
-               page = shmem_alloc_page(gfp, info, index);
-       if (page) {
-               __SetPageLocked(page);
-               __SetPageSwapBacked(page);
-               return page;
+               folio = shmem_alloc_folio(gfp, info, index);
+       if (folio) {
+               __folio_set_locked(folio);
+               __folio_set_swapbacked(folio);
+               return folio;
        }
 
        err = -ENOMEM;
@@ -1601,9 +1598,9 @@ failed:
  * NUMA mempolicy, and applied also to anonymous pages in do_swap_page();
  * but for now it is a simple matter of zone.
  */
-static bool shmem_should_replace_page(struct page *page, gfp_t gfp)
+static bool shmem_should_replace_folio(struct folio *folio, gfp_t gfp)
 {
-       return page_zonenum(page) > gfp_zone(gfp);
+       return folio_zonenum(folio) > gfp_zone(gfp);
 }
 
 static int shmem_replace_page(struct page **pagep, gfp_t gfp,
@@ -1682,8 +1679,8 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
  * Returns 0 and the page in pagep if success. On failure, returns the
  * error code and NULL in *pagep.
  */
-static int shmem_swapin_page(struct inode *inode, pgoff_t index,
-                            struct page **pagep, enum sgp_type sgp,
+static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
+                            struct folio **foliop, enum sgp_type sgp,
                             gfp_t gfp, struct vm_area_struct *vma,
                             vm_fault_t *fault_type)
 {
@@ -1691,12 +1688,13 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        struct shmem_inode_info *info = SHMEM_I(inode);
        struct mm_struct *charge_mm = vma ? vma->vm_mm : NULL;
        struct page *page;
+       struct folio *folio = NULL;
        swp_entry_t swap;
        int error;
 
-       VM_BUG_ON(!*pagep || !xa_is_value(*pagep));
-       swap = radix_to_swp_entry(*pagep);
-       *pagep = NULL;
+       VM_BUG_ON(!*foliop || !xa_is_value(*foliop));
+       swap = radix_to_swp_entry(*foliop);
+       *foliop = NULL;
 
        /* Look it up and read it in.. */
        page = lookup_swap_cache(swap, NULL, 0);
@@ -1714,33 +1712,35 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
                        goto failed;
                }
        }
+       folio = page_folio(page);
 
        /* We have to do this with page locked to prevent races */
-       lock_page(page);
-       if (!PageSwapCache(page) || page_private(page) != swap.val ||
+       folio_lock(folio);
+       if (!folio_test_swapcache(folio) ||
+           folio_swap_entry(folio).val != swap.val ||
            !shmem_confirm_swap(mapping, index, swap)) {
                error = -EEXIST;
                goto unlock;
        }
-       if (!PageUptodate(page)) {
+       if (!folio_test_uptodate(folio)) {
                error = -EIO;
                goto failed;
        }
-       wait_on_page_writeback(page);
+       folio_wait_writeback(folio);
 
        /*
         * Some architectures may have to restore extra metadata to the
-        * physical page after reading from swap.
+        * folio after reading from swap.
         */
-       arch_swap_restore(swap, page);
+       arch_swap_restore(swap, folio);
 
-       if (shmem_should_replace_page(page, gfp)) {
+       if (shmem_should_replace_folio(folio, gfp)) {
                error = shmem_replace_page(&page, gfp, info, index);
                if (error)
                        goto failed;
        }
 
-       error = shmem_add_to_page_cache(page, mapping, index,
+       error = shmem_add_to_page_cache(folio, mapping, index,
                                        swp_to_radix_entry(swap), gfp,
                                        charge_mm);
        if (error)
@@ -1752,21 +1752,21 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        spin_unlock_irq(&info->lock);
 
        if (sgp == SGP_WRITE)
-               mark_page_accessed(page);
+               folio_mark_accessed(folio);
 
-       delete_from_swap_cache(page);
-       set_page_dirty(page);
+       delete_from_swap_cache(&folio->page);
+       folio_mark_dirty(folio);
        swap_free(swap);
 
-       *pagep = page;
+       *foliop = folio;
        return 0;
 failed:
        if (!shmem_confirm_swap(mapping, index, swap))
                error = -EEXIST;
 unlock:
-       if (page) {
-               unlock_page(page);
-               put_page(page);
+       if (folio) {
+               folio_unlock(folio);
+               folio_put(folio);
        }
 
        return error;
@@ -1791,7 +1791,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
        struct shmem_inode_info *info = SHMEM_I(inode);
        struct shmem_sb_info *sbinfo;
        struct mm_struct *charge_mm;
-       struct page *page;
+       struct folio *folio;
        pgoff_t hindex = index;
        gfp_t huge_gfp;
        int error;
@@ -1809,39 +1809,37 @@ repeat:
        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)) {
-               error = shmem_swapin_page(inode, index, &page,
+       if (xa_is_value(folio)) {
+               error = shmem_swapin_folio(inode, index, &folio,
                                          sgp, gfp, vma, fault_type);
                if (error == -EEXIST)
                        goto repeat;
 
-               *pagep = page;
+               *pagep = &folio->page;
                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);
        }
 
        /*
@@ -1868,17 +1866,16 @@ repeat:
 
        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;
                /*
@@ -1897,29 +1894,26 @@ alloc_nohuge:
                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);
 
-       error = shmem_add_to_page_cache(page, mapping, hindex,
+       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) {
                /*
@@ -1950,22 +1944,21 @@ clear:
         * 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);
@@ -1974,24 +1967,24 @@ clear:
                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);
@@ -2239,11 +2232,7 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 
        file_accessed(file);
        vma->vm_ops = &shmem_vm_ops;
-       if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
-                       ((vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK) <
-                       (vma->vm_end & HPAGE_PMD_MASK)) {
-               khugepaged_enter(vma, vma->vm_flags);
-       }
+       khugepaged_enter_vma(vma, vma->vm_flags);
        return 0;
 }
 
@@ -2318,7 +2307,7 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
                           struct vm_area_struct *dst_vma,
                           unsigned long dst_addr,
                           unsigned long src_addr,
-                          bool zeropage,
+                          bool zeropage, bool wp_copy,
                           struct page **pagep)
 {
        struct inode *inode = file_inode(dst_vma->vm_file);
@@ -2327,6 +2316,7 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        gfp_t gfp = mapping_gfp_mask(mapping);
        pgoff_t pgoff = linear_page_index(dst_vma, dst_addr);
        void *page_kaddr;
+       struct folio *folio;
        struct page *page;
        int ret;
        pgoff_t max_off;
@@ -2385,13 +2375,14 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        if (unlikely(pgoff >= max_off))
                goto out_release;
 
-       ret = shmem_add_to_page_cache(page, mapping, pgoff, NULL,
+       folio = page_folio(page);
+       ret = shmem_add_to_page_cache(folio, mapping, pgoff, NULL,
                                      gfp & GFP_RECLAIM_MASK, dst_mm);
        if (ret)
                goto out_release;
 
        ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
-                                      page, true, false);
+                                      page, true, wp_copy);
        if (ret)
                goto out_delete_from_cache;
 
@@ -3888,7 +3879,7 @@ static struct file_system_type shmem_fs_type = {
        .fs_flags       = FS_USERNS_MOUNT,
 };
 
-int __init shmem_init(void)
+void __init shmem_init(void)
 {
        int error;
 
@@ -3913,14 +3904,13 @@ int __init shmem_init(void)
        else
                shmem_huge = SHMEM_HUGE_NEVER; /* just in case it was patched */
 #endif
-       return 0;
+       return;
 
 out1:
        unregister_filesystem(&shmem_fs_type);
 out2:
        shmem_destroy_inodecache();
        shm_mnt = ERR_PTR(error);
-       return error;
 }
 
 #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && defined(CONFIG_SYSFS)
@@ -3998,14 +3988,12 @@ static struct file_system_type shmem_fs_type = {
        .fs_flags       = FS_USERNS_MOUNT,
 };
 
-int __init shmem_init(void)
+void __init shmem_init(void)
 {
        BUG_ON(register_filesystem(&shmem_fs_type) != 0);
 
        shm_mnt = kern_mount(&shmem_fs_type);
        BUG_ON(IS_ERR(shm_mnt));
-
-       return 0;
 }
 
 int shmem_unuse(unsigned int type)
@@ -4145,11 +4133,7 @@ int shmem_zero_setup(struct vm_area_struct *vma)
        vma->vm_file = file;
        vma->vm_ops = &shmem_vm_ops;
 
-       if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
-                       ((vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK) <
-                       (vma->vm_end & HPAGE_PMD_MASK)) {
-               khugepaged_enter(vma, vma->vm_flags);
-       }
+       khugepaged_enter_vma(vma, vma->vm_flags);
 
        return 0;
 }