aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/file.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-04-03 22:31:22 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-05-06 17:39:42 -0400
commit2b777c9dd9ebbb2f8b6818d454cc5e6d7c1e3c8b (patch)
treeaceac852de465a0205a7073496126925620ea7cf /fs/ceph/file.c
parentf0d1bec9d58d4c038d0ac958c9af82be6eb18045 (diff)
ceph_sync_read: stop poking into iov_iter guts
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r--fs/ceph/file.c46
1 files changed, 18 insertions, 28 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index c9a24ba98c9a..672b0fedb17b 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -418,7 +418,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
418 struct page **pages; 418 struct page **pages;
419 u64 off = iocb->ki_pos; 419 u64 off = iocb->ki_pos;
420 int num_pages, ret; 420 int num_pages, ret;
421 size_t len = i->count; 421 size_t len = iov_iter_count(i);
422 422
423 dout("sync_read on file %p %llu~%u %s\n", file, off, 423 dout("sync_read on file %p %llu~%u %s\n", file, off,
424 (unsigned)len, 424 (unsigned)len,
@@ -436,25 +436,26 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
436 436
437 if (file->f_flags & O_DIRECT) { 437 if (file->f_flags & O_DIRECT) {
438 while (iov_iter_count(i)) { 438 while (iov_iter_count(i)) {
439 void __user *data = i->iov[0].iov_base + i->iov_offset; 439 size_t start;
440 size_t len = i->iov[0].iov_len - i->iov_offset; 440 ssize_t n;
441 441
442 num_pages = calc_pages_for((unsigned long)data, len); 442 n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start);
443 pages = ceph_get_direct_page_vector(data, 443 if (n < 0)
444 num_pages, true); 444 return n;
445 if (IS_ERR(pages))
446 return PTR_ERR(pages);
447 445
448 ret = striped_read(inode, off, len, 446 num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;
447
448 ret = striped_read(inode, off, n,
449 pages, num_pages, checkeof, 449 pages, num_pages, checkeof,
450 1, (unsigned long)data & ~PAGE_MASK); 450 1, start);
451
451 ceph_put_page_vector(pages, num_pages, true); 452 ceph_put_page_vector(pages, num_pages, true);
452 453
453 if (ret <= 0) 454 if (ret <= 0)
454 break; 455 break;
455 off += ret; 456 off += ret;
456 iov_iter_advance(i, ret); 457 iov_iter_advance(i, ret);
457 if (ret < len) 458 if (ret < n)
458 break; 459 break;
459 } 460 }
460 } else { 461 } else {
@@ -466,25 +467,14 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
466 num_pages, checkeof, 0, 0); 467 num_pages, checkeof, 0, 0);
467 if (ret > 0) { 468 if (ret > 0) {
468 int l, k = 0; 469 int l, k = 0;
469 size_t left = len = ret; 470 size_t left = ret;
470 471
471 while (left) { 472 while (left) {
472 void __user *data = i->iov[0].iov_base 473 int copy = min_t(size_t, PAGE_SIZE, left);
473 + i->iov_offset; 474 l = copy_page_to_iter(pages[k++], 0, copy, i);
474 l = min(i->iov[0].iov_len - i->iov_offset, 475 off += l;
475 left); 476 left -= l;
476 477 if (l < copy)
477 ret = ceph_copy_page_vector_to_user(&pages[k],
478 data, off,
479 l);
480 if (ret > 0) {
481 iov_iter_advance(i, ret);
482 left -= ret;
483 off += ret;
484 k = calc_pages_for(iocb->ki_pos,
485 len - left + 1) - 1;
486 BUG_ON(k >= num_pages && left);
487 } else
488 break; 478 break;
489 } 479 }
490 } 480 }