aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/direct.c66
1 files changed, 15 insertions, 51 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8f5d2dfd5a8a..6ecde9602f99 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -321,7 +321,7 @@ static ssize_t nfs_direct_read_wait(struct nfs_direct_req *dreq, int intr)
321 return (ssize_t) result; 321 return (ssize_t) result;
322} 322}
323 323
324static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages) 324static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages)
325{ 325{
326 ssize_t result; 326 ssize_t result;
327 sigset_t oldset; 327 sigset_t oldset;
@@ -346,48 +346,6 @@ static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context
346 return result; 346 return result;
347} 347}
348 348
349/*
350 * We've already pushed out any non-direct writes so that this read
351 * will see them when we read from the server.
352 */
353static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, const struct iovec *iov, loff_t file_offset, unsigned long nr_segs)
354{
355 ssize_t tot_bytes = 0;
356 unsigned long seg = 0;
357
358 while ((seg < nr_segs) && (tot_bytes >= 0)) {
359 ssize_t result;
360 int page_count;
361 struct page **pages;
362 const struct iovec *vec = &iov[seg++];
363 unsigned long user_addr = (unsigned long) vec->iov_base;
364 size_t size = vec->iov_len;
365
366 page_count = nfs_get_user_pages(READ, user_addr, size, &pages);
367 if (page_count < 0) {
368 nfs_free_user_pages(pages, 0, 0);
369 if (tot_bytes > 0)
370 break;
371 return page_count;
372 }
373
374 result = nfs_direct_read_seg(inode, ctx, user_addr, size,
375 file_offset, pages, page_count);
376
377 if (result <= 0) {
378 if (tot_bytes > 0)
379 break;
380 return result;
381 }
382 tot_bytes += result;
383 file_offset += result;
384 if (result < size)
385 break;
386 }
387
388 return tot_bytes;
389}
390
391static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, int nr_pages) 349static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, int nr_pages)
392{ 350{
393 const unsigned int wsize = NFS_SERVER(inode)->wsize; 351 const unsigned int wsize = NFS_SERVER(inode)->wsize;
@@ -559,16 +517,13 @@ static ssize_t nfs_direct_write(struct inode *inode, struct nfs_open_context *ct
559ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) 517ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
560{ 518{
561 ssize_t retval = -EINVAL; 519 ssize_t retval = -EINVAL;
562 loff_t *ppos = &iocb->ki_pos; 520 int page_count;
521 struct page **pages;
563 struct file *file = iocb->ki_filp; 522 struct file *file = iocb->ki_filp;
564 struct nfs_open_context *ctx = 523 struct nfs_open_context *ctx =
565 (struct nfs_open_context *) file->private_data; 524 (struct nfs_open_context *) file->private_data;
566 struct address_space *mapping = file->f_mapping; 525 struct address_space *mapping = file->f_mapping;
567 struct inode *inode = mapping->host; 526 struct inode *inode = mapping->host;
568 struct iovec iov = {
569 .iov_base = buf,
570 .iov_len = count,
571 };
572 527
573 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", 528 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
574 file->f_dentry->d_parent->d_name.name, 529 file->f_dentry->d_parent->d_name.name,
@@ -580,7 +535,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
580 if (count < 0) 535 if (count < 0)
581 goto out; 536 goto out;
582 retval = -EFAULT; 537 retval = -EFAULT;
583 if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len)) 538 if (!access_ok(VERIFY_WRITE, buf, count))
584 goto out; 539 goto out;
585 retval = 0; 540 retval = 0;
586 if (!count) 541 if (!count)
@@ -590,9 +545,18 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
590 if (retval) 545 if (retval)
591 goto out; 546 goto out;
592 547
593 retval = nfs_direct_read(inode, ctx, &iov, pos, 1); 548 page_count = nfs_get_user_pages(READ, (unsigned long) buf,
549 count, &pages);
550 if (page_count < 0) {
551 nfs_free_user_pages(pages, 0, 0);
552 retval = page_count;
553 goto out;
554 }
555
556 retval = nfs_direct_read(inode, ctx, (unsigned long) buf, count, pos,
557 pages, page_count);
594 if (retval > 0) 558 if (retval > 0)
595 *ppos = pos + retval; 559 iocb->ki_pos = pos + retval;
596 560
597out: 561out:
598 return retval; 562 return retval;