]> git.ipfire.org Git - people/ms/linux.git/blobdiff - fs/hugetlbfs/inode.c
Merge branch 'for-6.0/dax' into libnvdimm-fixes
[people/ms/linux.git] / fs / hugetlbfs / inode.c
index 02eb72351b15be706e6734e40a663c70da80efd9..f7a5b5124d8a92412778b2706838d599dfef0fee 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/thread_info.h>
 #include <asm/current.h>
-#include <linux/sched/signal.h>                /* remove ASAP */
 #include <linux/falloc.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -40,7 +39,6 @@
 #include <linux/uaccess.h>
 #include <linux/sched/mm.h>
 
-static const struct super_operations hugetlbfs_ops;
 static const struct address_space_operations hugetlbfs_aops;
 const struct file_operations hugetlbfs_file_operations;
 static const struct inode_operations hugetlbfs_dir_inode_operations;
@@ -108,16 +106,6 @@ static inline void hugetlb_drop_vma_policy(struct vm_area_struct *vma)
 }
 #endif
 
-static void huge_pagevec_release(struct pagevec *pvec)
-{
-       int i;
-
-       for (i = 0; i < pagevec_count(pvec); ++i)
-               put_page(pvec->pages[i]);
-
-       pagevec_reinit(pvec);
-}
-
 /*
  * Mask used when checking the page offset value passed in via system
  * calls.  This value will be converted to a loff_t which is signed.
@@ -294,39 +282,9 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 }
 #endif
 
-static size_t
-hugetlbfs_read_actor(struct page *page, unsigned long offset,
-                       struct iov_iter *to, unsigned long size)
-{
-       size_t copied = 0;
-       int i, chunksize;
-
-       /* Find which 4k chunk and offset with in that chunk */
-       i = offset >> PAGE_SHIFT;
-       offset = offset & ~PAGE_MASK;
-
-       while (size) {
-               size_t n;
-               chunksize = PAGE_SIZE;
-               if (offset)
-                       chunksize -= offset;
-               if (chunksize > size)
-                       chunksize = size;
-               n = copy_page_to_iter(&page[i], offset, chunksize, to);
-               copied += n;
-               if (n != chunksize)
-                       return copied;
-               offset = 0;
-               size -= chunksize;
-               i++;
-       }
-       return copied;
-}
-
 /*
  * Support for read() - Find the page attached to f_mapping and copy out the
- * data. Its *very* similar to generic_file_buffered_read(), we can't use that
- * since it has PAGE_SIZE assumptions.
+ * data. This provides functionality similar to filemap_read().
  */
 static ssize_t hugetlbfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
@@ -373,7 +331,7 @@ static ssize_t hugetlbfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
                        /*
                         * We have the page, copy it to user space buffer.
                         */
-                       copied = hugetlbfs_read_actor(page, offset, to, nr);
+                       copied = copy_page_to_iter(page, offset, nr, to);
                        put_page(page);
                }
                offset += copied;
@@ -480,25 +438,19 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
        struct address_space *mapping = &inode->i_data;
        const pgoff_t start = lstart >> huge_page_shift(h);
        const pgoff_t end = lend >> huge_page_shift(h);
-       struct pagevec pvec;
+       struct folio_batch fbatch;
        pgoff_t next, index;
        int i, freed = 0;
        bool truncate_op = (lend == LLONG_MAX);
 
-       pagevec_init(&pvec);
+       folio_batch_init(&fbatch);
        next = start;
-       while (next < end) {
-               /*
-                * When no more pages are found, we are done.
-                */
-               if (!pagevec_lookup_range(&pvec, mapping, &next, end - 1))
-                       break;
-
-               for (i = 0; i < pagevec_count(&pvec); ++i) {
-                       struct page *page = pvec.pages[i];
+       while (filemap_get_folios(mapping, &next, end - 1, &fbatch)) {
+               for (i = 0; i < folio_batch_count(&fbatch); ++i) {
+                       struct folio *folio = fbatch.folios[i];
                        u32 hash = 0;
 
-                       index = page->index;
+                       index = folio->index;
                        if (!truncate_op) {
                                /*
                                 * Only need to hold the fault mutex in the
@@ -511,15 +463,15 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                        }
 
                        /*
-                        * If page is mapped, it was faulted in after being
+                        * If folio is mapped, it was faulted in after being
                         * unmapped in caller.  Unmap (again) now after taking
                         * the fault mutex.  The mutex will prevent faults
-                        * until we finish removing the page.
+                        * until we finish removing the folio.
                         *
                         * This race can only happen in the hole punch case.
                         * Getting here in a truncate operation is a bug.
                         */
-                       if (unlikely(page_mapped(page))) {
+                       if (unlikely(folio_mapped(folio))) {
                                BUG_ON(truncate_op);
 
                                mutex_unlock(&hugetlb_fault_mutex_table[hash]);
@@ -532,7 +484,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                                i_mmap_unlock_write(mapping);
                        }
 
-                       lock_page(page);
+                       folio_lock(folio);
                        /*
                         * We must free the huge page and remove from page
                         * cache (remove_huge_page) BEFORE removing the
@@ -542,8 +494,8 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                         * the subpool and global reserve usage count can need
                         * to be adjusted.
                         */
-                       VM_BUG_ON(HPageRestoreReserve(page));
-                       remove_huge_page(page);
+                       VM_BUG_ON(HPageRestoreReserve(&folio->page));
+                       remove_huge_page(&folio->page);
                        freed++;
                        if (!truncate_op) {
                                if (unlikely(hugetlb_unreserve_pages(inode,
@@ -551,11 +503,11 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                                        hugetlb_fix_reserve_counts(inode);
                        }
 
-                       unlock_page(page);
+                       folio_unlock(folio);
                        if (!truncate_op)
                                mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                }
-               huge_pagevec_release(&pvec);
+               folio_batch_release(&fbatch);
                cond_resched();
        }
 
@@ -797,7 +749,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
 
                SetHPageMigratable(page);
                /*
-                * unlock_page because locked by add_to_page_cache()
+                * unlock_page because locked by huge_add_to_page_cache()
                 * put_page() due to reference from alloc_huge_page()
                 */
                unlock_page(page);
@@ -1008,28 +960,33 @@ static int hugetlbfs_symlink(struct user_namespace *mnt_userns,
        return error;
 }
 
-static int hugetlbfs_migrate_page(struct address_space *mapping,
-                               struct page *newpage, struct page *page,
+#ifdef CONFIG_MIGRATION
+static int hugetlbfs_migrate_folio(struct address_space *mapping,
+                               struct folio *dst, struct folio *src,
                                enum migrate_mode mode)
 {
        int rc;
 
-       rc = migrate_huge_page_move_mapping(mapping, newpage, page);
+       rc = migrate_huge_page_move_mapping(mapping, dst, src);
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
 
-       if (hugetlb_page_subpool(page)) {
-               hugetlb_set_page_subpool(newpage, hugetlb_page_subpool(page));
-               hugetlb_set_page_subpool(page, NULL);
+       if (hugetlb_page_subpool(&src->page)) {
+               hugetlb_set_page_subpool(&dst->page,
+                                       hugetlb_page_subpool(&src->page));
+               hugetlb_set_page_subpool(&src->page, NULL);
        }
 
        if (mode != MIGRATE_SYNC_NO_COPY)
-               migrate_page_copy(newpage, page);
+               folio_migrate_copy(dst, src);
        else
-               migrate_page_states(newpage, page);
+               folio_migrate_flags(dst, src);
 
        return MIGRATEPAGE_SUCCESS;
 }
+#else
+#define hugetlbfs_migrate_folio NULL
+#endif
 
 static int hugetlbfs_error_remove_page(struct address_space *mapping,
                                struct page *page)
@@ -1093,7 +1050,7 @@ static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_bsize = huge_page_size(h);
        if (sbinfo) {
                spin_lock(&sbinfo->stat_lock);
-               /* If no limits set, just report 0 for max/free/used
+               /* If no limits set, just report 0 or -1 for max/free/used
                 * blocks, like simple_statfs() */
                if (sbinfo->spool) {
                        long free_pages;
@@ -1196,7 +1153,7 @@ static const struct address_space_operations hugetlbfs_aops = {
        .write_begin    = hugetlbfs_write_begin,
        .write_end      = hugetlbfs_write_end,
        .dirty_folio    = noop_dirty_folio,
-       .migratepage    = hugetlbfs_migrate_page,
+       .migrate_folio  = hugetlbfs_migrate_folio,
        .error_remove_page      = hugetlbfs_error_remove_page,
 };
 
@@ -1320,7 +1277,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par
                ps = memparse(param->string, &rest);
                ctx->hstate = size_to_hstate(ps);
                if (!ctx->hstate) {
-                       pr_err("Unsupported page size %lu MB\n", ps >> 20);
+                       pr_err("Unsupported page size %lu MB\n", ps / SZ_1M);
                        return -EINVAL;
                }
                return 0;
@@ -1396,7 +1353,7 @@ hugetlbfs_fill_super(struct super_block *sb, struct fs_context *fc)
        /*
         * Allocate and initialize subpool if maximum or minimum size is
         * specified.  Any needed reservations (for minimum size) are taken
-        * taken when the subpool is created.
+        * when the subpool is created.
         */
        if (ctx->max_hpages != -1 || ctx->min_hpages != -1) {
                sbinfo->spool = hugepage_new_subpool(ctx->hstate,
@@ -1566,7 +1523,7 @@ static struct vfsmount *__init mount_one_hugetlbfs(struct hstate *h)
        }
        if (IS_ERR(mnt))
                pr_err("Cannot mount internal hugetlbfs for page size %luK",
-                      huge_page_size(h) >> 10);
+                      huge_page_size(h) / SZ_1K);
        return mnt;
 }