struct sg_table *sg;
        struct miscdevice *device;
        pgoff_t *offsets;
+       struct list_head unpin_list;
+};
+
+struct udmabuf_folio {
+       struct folio *folio;
+       struct list_head list;
 };
 
 static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
        return put_sg_table(at->dev, sg, direction);
 }
 
+static void unpin_all_folios(struct list_head *unpin_list)
+{
+       struct udmabuf_folio *ubuf_folio;
+
+       while (!list_empty(unpin_list)) {
+               ubuf_folio = list_first_entry(unpin_list,
+                                             struct udmabuf_folio, list);
+               unpin_folio(ubuf_folio->folio);
+
+               list_del(&ubuf_folio->list);
+               kfree(ubuf_folio);
+       }
+}
+
+static int add_to_unpin_list(struct list_head *unpin_list,
+                            struct folio *folio)
+{
+       struct udmabuf_folio *ubuf_folio;
+
+       ubuf_folio = kzalloc(sizeof(*ubuf_folio), GFP_KERNEL);
+       if (!ubuf_folio)
+               return -ENOMEM;
+
+       ubuf_folio->folio = folio;
+       list_add_tail(&ubuf_folio->list, unpin_list);
+       return 0;
+}
+
 static void release_udmabuf(struct dma_buf *buf)
 {
        struct udmabuf *ubuf = buf->priv;
        struct device *dev = ubuf->device->this_device;
-       pgoff_t pg;
 
        if (ubuf->sg)
                put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL);
 
-       for (pg = 0; pg < ubuf->pagecount; pg++)
-               folio_put(ubuf->folios[pg]);
+       unpin_all_folios(&ubuf->unpin_list);
        kfree(ubuf->offsets);
        kfree(ubuf->folios);
        kfree(ubuf);
 #define SEALS_WANTED (F_SEAL_SHRINK)
 #define SEALS_DENIED (F_SEAL_WRITE)
 
-static int handle_hugetlb_pages(struct udmabuf *ubuf, struct file *memfd,
-                               pgoff_t offset, pgoff_t pgcnt,
-                               pgoff_t *pgbuf)
-{
-       struct hstate *hpstate = hstate_file(memfd);
-       pgoff_t mapidx = offset >> huge_page_shift(hpstate);
-       pgoff_t subpgoff = (offset & ~huge_page_mask(hpstate)) >> PAGE_SHIFT;
-       pgoff_t maxsubpgs = huge_page_size(hpstate) >> PAGE_SHIFT;
-       struct folio *folio = NULL;
-       pgoff_t pgidx;
-
-       mapidx <<= huge_page_order(hpstate);
-       for (pgidx = 0; pgidx < pgcnt; pgidx++) {
-               if (!folio) {
-                       folio = __filemap_get_folio(memfd->f_mapping,
-                                                   mapidx,
-                                                   FGP_ACCESSED, 0);
-                       if (IS_ERR(folio))
-                               return PTR_ERR(folio);
-               }
-
-               folio_get(folio);
-               ubuf->folios[*pgbuf] = folio;
-               ubuf->offsets[*pgbuf] = subpgoff << PAGE_SHIFT;
-               (*pgbuf)++;
-               if (++subpgoff == maxsubpgs) {
-                       folio_put(folio);
-                       folio = NULL;
-                       subpgoff = 0;
-                       mapidx += pages_per_huge_page(hpstate);
-               }
-       }
-
-       if (folio)
-               folio_put(folio);
-
-       return 0;
-}
-
-static int handle_shmem_pages(struct udmabuf *ubuf, struct file *memfd,
-                             pgoff_t offset, pgoff_t pgcnt,
-                             pgoff_t *pgbuf)
-{
-       pgoff_t pgidx, pgoff = offset >> PAGE_SHIFT;
-       struct folio *folio = NULL;
-
-       for (pgidx = 0; pgidx < pgcnt; pgidx++) {
-               folio = shmem_read_folio(memfd->f_mapping, pgoff + pgidx);
-               if (IS_ERR(folio))
-                       return PTR_ERR(folio);
-
-               ubuf->folios[*pgbuf] = folio;
-               (*pgbuf)++;
-       }
-
-       return 0;
-}
-
 static int check_memfd_seals(struct file *memfd)
 {
        int seals;
                           struct udmabuf_create_list *head,
                           struct udmabuf_create_item *list)
 {
-       pgoff_t pgcnt, pgbuf = 0, pglimit;
+       pgoff_t pgoff, pgcnt, pglimit, pgbuf = 0;
+       long nr_folios, ret = -EINVAL;
        struct file *memfd = NULL;
+       struct folio **folios;
        struct udmabuf *ubuf;
-       int ret = -EINVAL;
-       u32 i, flags;
+       u32 i, j, k, flags;
+       loff_t end;
 
        ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
        if (!ubuf)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&ubuf->unpin_list);
        pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
        for (i = 0; i < head->count; i++) {
                if (!IS_ALIGNED(list[i].offset, PAGE_SIZE))
                        goto err;
 
                pgcnt = list[i].size >> PAGE_SHIFT;
-               if (is_file_hugepages(memfd))
-                       ret = handle_hugetlb_pages(ubuf, memfd,
-                                                  list[i].offset,
-                                                  pgcnt, &pgbuf);
-               else
-                       ret = handle_shmem_pages(ubuf, memfd,
-                                                list[i].offset,
-                                                pgcnt, &pgbuf);
-               if (ret < 0)
+               folios = kmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL);
+               if (!folios) {
+                       ret = -ENOMEM;
                        goto err;
+               }
+
+               end = list[i].offset + (pgcnt << PAGE_SHIFT) - 1;
+               ret = memfd_pin_folios(memfd, list[i].offset, end,
+                                      folios, pgcnt, &pgoff);
+               if (ret <= 0) {
+                       kfree(folios);
+                       if (!ret)
+                               ret = -EINVAL;
+                       goto err;
+               }
+
+               nr_folios = ret;
+               pgoff >>= PAGE_SHIFT;
+               for (j = 0, k = 0; j < pgcnt; j++) {
+                       ubuf->folios[pgbuf] = folios[k];
+                       ubuf->offsets[pgbuf] = pgoff << PAGE_SHIFT;
+
+                       if (j == 0 || ubuf->folios[pgbuf-1] != folios[k]) {
+                               ret = add_to_unpin_list(&ubuf->unpin_list,
+                                                       folios[k]);
+                               if (ret < 0) {
+                                       kfree(folios);
+                                       goto err;
+                               }
+                       }
+
+                       pgbuf++;
+                       if (++pgoff == folio_nr_pages(folios[k])) {
+                               pgoff = 0;
+                               if (++k == nr_folios)
+                                       break;
+                       }
+               }
 
+               kfree(folios);
                fput(memfd);
                memfd = NULL;
        }
        return ret;
 
 err:
-       while (pgbuf > 0)
-               folio_put(ubuf->folios[--pgbuf]);
        if (memfd)
                fput(memfd);
+       unpin_all_folios(&ubuf->unpin_list);
        kfree(ubuf->offsets);
        kfree(ubuf->folios);
        kfree(ubuf);