Commit bc40d73c950146725e9e768e856a416ec8949065

Authored by Nick Piggin
Committed by Linus Torvalds
1 parent f5dd33c494

splice: use get_user_pages_fast

Use get_user_pages_fast in splice.  This reverts some mmap_sem batching
there, however the biggest problem with mmap_sem tends to be hold times
blocking out other threads rather than cacheline bouncing.  Further: on
architectures that implement get_user_pages_fast without locks, mmap_sem
can be avoided completely anyway.

Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Dave Kleikamp <shaggy@austin.ibm.com>
Cc: Andy Whitcroft <apw@shadowen.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Dave Kleikamp <shaggy@austin.ibm.com>
Cc: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Zach Brown <zach.brown@oracle.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Reviewed-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 3 additions and 38 deletions Side-by-side Diff

... ... @@ -1161,36 +1161,6 @@
1161 1161 }
1162 1162  
1163 1163 /*
1164   - * Do a copy-from-user while holding the mmap_semaphore for reading, in a
1165   - * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem
1166   - * for writing) and page faulting on the user memory pointed to by src.
1167   - * This assumes that we will very rarely hit the partial != 0 path, or this
1168   - * will not be a win.
1169   - */
1170   -static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n)
1171   -{
1172   - int partial;
1173   -
1174   - if (!access_ok(VERIFY_READ, src, n))
1175   - return -EFAULT;
1176   -
1177   - pagefault_disable();
1178   - partial = __copy_from_user_inatomic(dst, src, n);
1179   - pagefault_enable();
1180   -
1181   - /*
1182   - * Didn't copy everything, drop the mmap_sem and do a faulting copy
1183   - */
1184   - if (unlikely(partial)) {
1185   - up_read(&current->mm->mmap_sem);
1186   - partial = copy_from_user(dst, src, n);
1187   - down_read(&current->mm->mmap_sem);
1188   - }
1189   -
1190   - return partial;
1191   -}
1192   -
1193   -/*
1194 1164 * Map an iov into an array of pages and offset/length tupples. With the
1195 1165 * partial_page structure, we can map several non-contiguous ranges into
1196 1166 * our ones pages[] map instead of splitting that operation into pieces.
... ... @@ -1203,8 +1173,6 @@
1203 1173 {
1204 1174 int buffers = 0, error = 0;
1205 1175  
1206   - down_read(&current->mm->mmap_sem);
1207   -
1208 1176 while (nr_vecs) {
1209 1177 unsigned long off, npages;
1210 1178 struct iovec entry;
... ... @@ -1213,7 +1181,7 @@
1213 1181 int i;
1214 1182  
1215 1183 error = -EFAULT;
1216   - if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry)))
  1184 + if (copy_from_user(&entry, iov, sizeof(entry)))
1217 1185 break;
1218 1186  
1219 1187 base = entry.iov_base;
... ... @@ -1247,9 +1215,8 @@
1247 1215 if (npages > PIPE_BUFFERS - buffers)
1248 1216 npages = PIPE_BUFFERS - buffers;
1249 1217  
1250   - error = get_user_pages(current, current->mm,
1251   - (unsigned long) base, npages, 0, 0,
1252   - &pages[buffers], NULL);
  1218 + error = get_user_pages_fast((unsigned long)base, npages,
  1219 + 0, &pages[buffers]);
1253 1220  
1254 1221 if (unlikely(error <= 0))
1255 1222 break;
... ... @@ -1287,8 +1254,6 @@
1287 1254 nr_vecs--;
1288 1255 iov++;
1289 1256 }
1290   -
1291   - up_read(&current->mm->mmap_sem);
1292 1257  
1293 1258 if (buffers)
1294 1259 return buffers;