diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 66 |
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 | ||
324 | static 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) | 324 | static 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 | */ | ||
353 | static 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 | |||
391 | static 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) | 349 | static 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 | |||
559 | ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) | 517 | ssize_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 | ||
597 | out: | 561 | out: |
598 | return retval; | 562 | return retval; |