[PATCH] mm/gup: Use put_user_page*() instead of put_page*()
From: Bharath Vedartham <hidden>
Date: 2019-07-14 19:11:32
Also in:
bpf, kvm, linux-fsdevel, linux-media, linux-mm, lkml, netdev
Subsystem:
char and misc drivers, filesystems (vfs and infrastructure), media input infrastructure (v4l/dvb), memory management, networking [general], sgi gru driver, staging subsystem, the rest, vfio driver, xdp sockets (af_xdp) · Maintainers:
Arnd Bergmann, Greg Kroah-Hartman, Alexander Viro, Christian Brauner, Mauro Carvalho Chehab, Andrew Morton, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Dimitri Sivanich, Linus Torvalds, Alex Williamson, Magnus Karlsson, Maciej Fijalkowski
This patch converts all call sites of get_user_pages to use put_user_page*() instead of put_page*() functions to release reference to gup pinned pages. This is a bunch of trivial conversions which is a part of an effort by John Hubbard to solve issues with gup pinned pages and filesystem writeback. The issue is more clearly described in John Hubbard's patch[1] where put_user_page*() functions are introduced. Currently put_user_page*() simply does put_page but future implementations look to change that once treewide change of put_page callsites to put_user_page*() is finished. The lwn article describing the issue with gup pinned pages and filesystem writeback [2]. This patch has been tested by building and booting the kernel as I don't have the required hardware to test the device drivers. I did not modify gpu/drm drivers which use release_pages instead of put_page() to release reference of gup pinned pages as I am not clear whether release_pages and put_page are interchangable. [1] https://lkml.org/lkml/2019/3/26/1396 [2] https://lwn.net/Articles/784574/ Signed-off-by: Bharath Vedartham <redacted> --- drivers/media/v4l2-core/videobuf-dma-sg.c | 3 +-- drivers/misc/sgi-gru/grufault.c | 2 +- drivers/staging/kpc2000/kpc_dma/fileops.c | 4 +--- drivers/vfio/vfio_iommu_type1.c | 2 +- fs/io_uring.c | 7 +++---- mm/gup_benchmark.c | 6 +----- net/xdp/xdp_umem.c | 7 +------ 7 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 66a6c6c..d6eeb43 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c@@ -349,8 +349,7 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) BUG_ON(dma->sglen); if (dma->pages) { - for (i = 0; i < dma->nr_pages; i++) - put_page(dma->pages[i]); + put_user_pages(dma->pages, dma->nr_pages); kfree(dma->pages); dma->pages = NULL; }
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 4b713a8..61b3447 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c@@ -188,7 +188,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma, if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0) return -EFAULT; *paddr = page_to_phys(page); - put_page(page); + put_user_page(page); return 0; }
diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
index 6166587..26dceed 100644
--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
+++ b/drivers/staging/kpc2000/kpc_dma/fileops.c@@ -198,9 +198,7 @@ int kpc_dma_transfer(struct dev_private_data *priv, struct kiocb *kcb, unsigned sg_free_table(&acd->sgt); err_dma_map_sg: err_alloc_sg_table: - for (i = 0 ; i < acd->page_count ; i++){ - put_page(acd->user_pages[i]); - } + put_user_pages(acd->user_pages, acd->page_count); err_get_user_pages: kfree(acd->user_pages); err_alloc_userpages:
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index add34ad..c491524 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c@@ -369,7 +369,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, */ if (ret > 0 && vma_is_fsdax(vmas[0])) { ret = -EOPNOTSUPP; - put_page(page[0]); + put_user_page(page[0]); } } up_read(&mm->mmap_sem);
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 4ef62a4..b4a4549 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c@@ -2694,10 +2694,9 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, * if we did partial map, or found file backed vmas, * release any pages we did get */ - if (pret > 0) { - for (j = 0; j < pret; j++) - put_page(pages[j]); - } + if (pret > 0) + put_user_pages(pages, pret); + if (ctx->account_mem) io_unaccount_mem(ctx->user, nr_pages); kvfree(imu->bvec);
diff --git a/mm/gup_benchmark.c b/mm/gup_benchmark.c
index 7dd602d..15fc7a2 100644
--- a/mm/gup_benchmark.c
+++ b/mm/gup_benchmark.c@@ -76,11 +76,7 @@ static int __gup_benchmark_ioctl(unsigned int cmd, gup->size = addr - gup->addr; start_time = ktime_get(); - for (i = 0; i < nr_pages; i++) { - if (!pages[i]) - break; - put_page(pages[i]); - } + put_user_pages(pages, nr_pages); end_time = ktime_get(); gup->put_delta_usec = ktime_us_delta(end_time, start_time);
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 9c6de4f..6103e19 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c@@ -173,12 +173,7 @@ static void xdp_umem_unpin_pages(struct xdp_umem *umem) { unsigned int i; - for (i = 0; i < umem->npgs; i++) { - struct page *page = umem->pgs[i]; - - set_page_dirty_lock(page); - put_page(page); - } + put_user_pages_dirty_lock(umem->pgs, umem->npgs); kfree(umem->pgs); umem->pgs = NULL;
--
1.8.3.1