aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-10-01 01:32:33 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2016-10-01 01:32:33 -0400
commitacbe5fda1fc05dc2e1e179b90c0879a5cfbf87b0 (patch)
tree4330ac667145090676c1d6512accc644280e66d9 /fs/fuse
parent3daa9c51651f2631be373840db0f82a8efb1c63d (diff)
fuse: don't use fuse_ioctl_copy_user() helper
The two invocations share little code. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/file.c52
1 files changed, 18 insertions, 34 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4c1db6ce7c48..b7beb67bf005 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2326,33 +2326,6 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
2326 return retval; 2326 return retval;
2327} 2327}
2328 2328
2329static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
2330 unsigned int nr_segs, size_t bytes, bool to_user)
2331{
2332 struct iov_iter ii;
2333 int page_idx = 0;
2334
2335 if (!bytes)
2336 return 0;
2337
2338 iov_iter_init(&ii, to_user ? READ : WRITE, iov, nr_segs, bytes);
2339
2340 while (iov_iter_count(&ii)) {
2341 struct page *page = pages[page_idx++];
2342 size_t copied;
2343
2344 if (!to_user)
2345 copied = copy_page_from_iter(page, 0, PAGE_SIZE, &ii);
2346 else
2347 copied = copy_page_to_iter(page, 0, PAGE_SIZE, &ii);
2348
2349 if (unlikely(copied != PAGE_SIZE && iov_iter_count(&ii)))
2350 return -EFAULT;
2351 }
2352
2353 return 0;
2354}
2355
2356/* 2329/*
2357 * CUSE servers compiled on 32bit broke on 64bit kernels because the 2330 * CUSE servers compiled on 32bit broke on 64bit kernels because the
2358 * ABI was defined to be 'struct iovec' which is different on 32bit 2331 * ABI was defined to be 'struct iovec' which is different on 32bit
@@ -2504,8 +2477,9 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
2504 struct iovec *iov_page = NULL; 2477 struct iovec *iov_page = NULL;
2505 struct iovec *in_iov = NULL, *out_iov = NULL; 2478 struct iovec *in_iov = NULL, *out_iov = NULL;
2506 unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages; 2479 unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages;
2507 size_t in_size, out_size, transferred; 2480 size_t in_size, out_size, transferred, c;
2508 int err; 2481 int err, i;
2482 struct iov_iter ii;
2509 2483
2510#if BITS_PER_LONG == 32 2484#if BITS_PER_LONG == 32
2511 inarg.flags |= FUSE_IOCTL_32BIT; 2485 inarg.flags |= FUSE_IOCTL_32BIT;
@@ -2587,10 +2561,13 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
2587 req->in.args[1].size = in_size; 2561 req->in.args[1].size = in_size;
2588 req->in.argpages = 1; 2562 req->in.argpages = 1;
2589 2563
2590 err = fuse_ioctl_copy_user(pages, in_iov, in_iovs, in_size, 2564 err = -EFAULT;
2591 false); 2565 iov_iter_init(&ii, WRITE, in_iov, in_iovs, in_size);
2592 if (err) 2566 for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= num_pages); i++) {
2593 goto out; 2567 c = copy_page_from_iter(pages[i], 0, PAGE_SIZE, &ii);
2568 if (c != PAGE_SIZE && iov_iter_count(&ii))
2569 goto out;
2570 }
2594 } 2571 }
2595 2572
2596 req->out.numargs = 2; 2573 req->out.numargs = 2;
@@ -2656,7 +2633,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
2656 if (transferred > inarg.out_size) 2633 if (transferred > inarg.out_size)
2657 goto out; 2634 goto out;
2658 2635
2659 err = fuse_ioctl_copy_user(pages, out_iov, out_iovs, transferred, true); 2636 err = -EFAULT;
2637 iov_iter_init(&ii, READ, out_iov, out_iovs, transferred);
2638 for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= num_pages); i++) {
2639 c = copy_page_to_iter(pages[i], 0, PAGE_SIZE, &ii);
2640 if (c != PAGE_SIZE && iov_iter_count(&ii))
2641 goto out;
2642 }
2643 err = 0;
2660 out: 2644 out:
2661 if (req) 2645 if (req)
2662 fuse_put_request(fc, req); 2646 fuse_put_request(fc, req);