diff options
author | Andrea Arcangeli <aarcange@redhat.com> | 2015-02-11 18:27:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 20:06:05 -0500 |
commit | 7e339128496284cc21977fba5416166ee81f5172 (patch) | |
tree | 6af95386953cc67f3f465b966e03cb56f184dd30 | |
parent | a7b780750e1a1c7833812681e1f8fa30bbb06802 (diff) |
mm: gup: use get_user_pages_unlocked
This allows those get_user_pages calls to pass FAULT_FLAG_ALLOW_RETRY to
the page fault in order to release the mmap_sem during the I/O.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Andres Lagar-Cavilla <andreslc@google.com>
Cc: Peter Feiner <pfeiner@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-udma.c | 6 | ||||
-rw-r--r-- | drivers/scsi/st.c | 7 | ||||
-rw-r--r-- | drivers/video/fbdev/pvr2fb.c | 6 | ||||
-rw-r--r-- | mm/process_vm_access.c | 7 | ||||
-rw-r--r-- | net/ceph/pagevec.c | 6 |
5 files changed, 10 insertions, 22 deletions
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c index bee2329e0b2e..24152accc66c 100644 --- a/drivers/media/pci/ivtv/ivtv-udma.c +++ b/drivers/media/pci/ivtv/ivtv-udma.c | |||
@@ -124,10 +124,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* Get user pages for DMA Xfer */ | 126 | /* Get user pages for DMA Xfer */ |
127 | down_read(¤t->mm->mmap_sem); | 127 | err = get_user_pages_unlocked(current, current->mm, |
128 | err = get_user_pages(current, current->mm, | 128 | user_dma.uaddr, user_dma.page_count, 0, 1, dma->map); |
129 | user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL); | ||
130 | up_read(¤t->mm->mmap_sem); | ||
131 | 129 | ||
132 | if (user_dma.page_count != err) { | 130 | if (user_dma.page_count != err) { |
133 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", | 131 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 128d3b55bdd9..9a1c34205254 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -4551,18 +4551,15 @@ static int sgl_map_user_pages(struct st_buffer *STbp, | |||
4551 | return -ENOMEM; | 4551 | return -ENOMEM; |
4552 | 4552 | ||
4553 | /* Try to fault in all of the necessary pages */ | 4553 | /* Try to fault in all of the necessary pages */ |
4554 | down_read(¤t->mm->mmap_sem); | ||
4555 | /* rw==READ means read from drive, write into memory area */ | 4554 | /* rw==READ means read from drive, write into memory area */ |
4556 | res = get_user_pages( | 4555 | res = get_user_pages_unlocked( |
4557 | current, | 4556 | current, |
4558 | current->mm, | 4557 | current->mm, |
4559 | uaddr, | 4558 | uaddr, |
4560 | nr_pages, | 4559 | nr_pages, |
4561 | rw == READ, | 4560 | rw == READ, |
4562 | 0, /* don't force */ | 4561 | 0, /* don't force */ |
4563 | pages, | 4562 | pages); |
4564 | NULL); | ||
4565 | up_read(¤t->mm->mmap_sem); | ||
4566 | 4563 | ||
4567 | /* Errors and no page mapped should return here */ | 4564 | /* Errors and no page mapped should return here */ |
4568 | if (res < nr_pages) | 4565 | if (res < nr_pages) |
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 7c74f58fc101..0e24eb9c219c 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c | |||
@@ -686,10 +686,8 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | |||
686 | if (!pages) | 686 | if (!pages) |
687 | return -ENOMEM; | 687 | return -ENOMEM; |
688 | 688 | ||
689 | down_read(¤t->mm->mmap_sem); | 689 | ret = get_user_pages_unlocked(current, current->mm, (unsigned long)buf, |
690 | ret = get_user_pages(current, current->mm, (unsigned long)buf, | 690 | nr_pages, WRITE, 0, pages); |
691 | nr_pages, WRITE, 0, pages, NULL); | ||
692 | up_read(¤t->mm->mmap_sem); | ||
693 | 691 | ||
694 | if (ret < nr_pages) { | 692 | if (ret < nr_pages) { |
695 | nr_pages = ret; | 693 | nr_pages = ret; |
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 5077afcd9e11..b1597690530c 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c | |||
@@ -99,11 +99,8 @@ static int process_vm_rw_single_vec(unsigned long addr, | |||
99 | size_t bytes; | 99 | size_t bytes; |
100 | 100 | ||
101 | /* Get the pages we're interested in */ | 101 | /* Get the pages we're interested in */ |
102 | down_read(&mm->mmap_sem); | 102 | pages = get_user_pages_unlocked(task, mm, pa, pages, |
103 | pages = get_user_pages(task, mm, pa, pages, | 103 | vm_write, 0, process_pages); |
104 | vm_write, 0, process_pages, NULL); | ||
105 | up_read(&mm->mmap_sem); | ||
106 | |||
107 | if (pages <= 0) | 104 | if (pages <= 0) |
108 | return -EFAULT; | 105 | return -EFAULT; |
109 | 106 | ||
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 555013034f7a..096d91447e06 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c | |||
@@ -23,17 +23,15 @@ struct page **ceph_get_direct_page_vector(const void __user *data, | |||
23 | if (!pages) | 23 | if (!pages) |
24 | return ERR_PTR(-ENOMEM); | 24 | return ERR_PTR(-ENOMEM); |
25 | 25 | ||
26 | down_read(¤t->mm->mmap_sem); | ||
27 | while (got < num_pages) { | 26 | while (got < num_pages) { |
28 | rc = get_user_pages(current, current->mm, | 27 | rc = get_user_pages_unlocked(current, current->mm, |
29 | (unsigned long)data + ((unsigned long)got * PAGE_SIZE), | 28 | (unsigned long)data + ((unsigned long)got * PAGE_SIZE), |
30 | num_pages - got, write_page, 0, pages + got, NULL); | 29 | num_pages - got, write_page, 0, pages + got); |
31 | if (rc < 0) | 30 | if (rc < 0) |
32 | break; | 31 | break; |
33 | BUG_ON(rc == 0); | 32 | BUG_ON(rc == 0); |
34 | got += rc; | 33 | got += rc; |
35 | } | 34 | } |
36 | up_read(¤t->mm->mmap_sem); | ||
37 | if (rc < 0) | 35 | if (rc < 0) |
38 | goto fail; | 36 | goto fail; |
39 | return pages; | 37 | return pages; |