diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 00eee87510fe..a5c82b6f3b45 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -266,7 +266,7 @@ static const struct rpc_call_ops nfs_read_direct_ops = { | |||
266 | static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) | 266 | static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) |
267 | { | 267 | { |
268 | struct nfs_open_context *ctx = dreq->ctx; | 268 | struct nfs_open_context *ctx = dreq->ctx; |
269 | struct inode *inode = ctx->dentry->d_inode; | 269 | struct inode *inode = ctx->path.dentry->d_inode; |
270 | size_t rsize = NFS_SERVER(inode)->rsize; | 270 | size_t rsize = NFS_SERVER(inode)->rsize; |
271 | unsigned int pgbase; | 271 | unsigned int pgbase; |
272 | int result; | 272 | int result; |
@@ -295,9 +295,14 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
295 | break; | 295 | break; |
296 | } | 296 | } |
297 | if ((unsigned)result < data->npages) { | 297 | if ((unsigned)result < data->npages) { |
298 | nfs_direct_release_pages(data->pagevec, result); | 298 | bytes = result * PAGE_SIZE; |
299 | nfs_readdata_release(data); | 299 | if (bytes <= pgbase) { |
300 | break; | 300 | nfs_direct_release_pages(data->pagevec, result); |
301 | nfs_readdata_release(data); | ||
302 | break; | ||
303 | } | ||
304 | bytes -= pgbase; | ||
305 | data->npages = result; | ||
301 | } | 306 | } |
302 | 307 | ||
303 | get_dreq(dreq); | 308 | get_dreq(dreq); |
@@ -601,7 +606,7 @@ static const struct rpc_call_ops nfs_write_direct_ops = { | |||
601 | static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) | 606 | static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) |
602 | { | 607 | { |
603 | struct nfs_open_context *ctx = dreq->ctx; | 608 | struct nfs_open_context *ctx = dreq->ctx; |
604 | struct inode *inode = ctx->dentry->d_inode; | 609 | struct inode *inode = ctx->path.dentry->d_inode; |
605 | size_t wsize = NFS_SERVER(inode)->wsize; | 610 | size_t wsize = NFS_SERVER(inode)->wsize; |
606 | unsigned int pgbase; | 611 | unsigned int pgbase; |
607 | int result; | 612 | int result; |
@@ -630,9 +635,14 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
630 | break; | 635 | break; |
631 | } | 636 | } |
632 | if ((unsigned)result < data->npages) { | 637 | if ((unsigned)result < data->npages) { |
633 | nfs_direct_release_pages(data->pagevec, result); | 638 | bytes = result * PAGE_SIZE; |
634 | nfs_writedata_release(data); | 639 | if (bytes <= pgbase) { |
635 | break; | 640 | nfs_direct_release_pages(data->pagevec, result); |
641 | nfs_writedata_release(data); | ||
642 | break; | ||
643 | } | ||
644 | bytes -= pgbase; | ||
645 | data->npages = result; | ||
636 | } | 646 | } |
637 | 647 | ||
638 | get_dreq(dreq); | 648 | get_dreq(dreq); |
@@ -763,10 +773,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
763 | (unsigned long) count, (long long) pos); | 773 | (unsigned long) count, (long long) pos); |
764 | 774 | ||
765 | if (nr_segs != 1) | 775 | if (nr_segs != 1) |
766 | return -EINVAL; | ||
767 | |||
768 | if (count < 0) | ||
769 | goto out; | 776 | goto out; |
777 | |||
770 | retval = -EFAULT; | 778 | retval = -EFAULT; |
771 | if (!access_ok(VERIFY_WRITE, buf, count)) | 779 | if (!access_ok(VERIFY_WRITE, buf, count)) |
772 | goto out; | 780 | goto out; |
@@ -814,7 +822,7 @@ out: | |||
814 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | 822 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, |
815 | unsigned long nr_segs, loff_t pos) | 823 | unsigned long nr_segs, loff_t pos) |
816 | { | 824 | { |
817 | ssize_t retval; | 825 | ssize_t retval = -EINVAL; |
818 | struct file *file = iocb->ki_filp; | 826 | struct file *file = iocb->ki_filp; |
819 | struct address_space *mapping = file->f_mapping; | 827 | struct address_space *mapping = file->f_mapping; |
820 | /* XXX: temporary */ | 828 | /* XXX: temporary */ |
@@ -827,7 +835,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
827 | (unsigned long) count, (long long) pos); | 835 | (unsigned long) count, (long long) pos); |
828 | 836 | ||
829 | if (nr_segs != 1) | 837 | if (nr_segs != 1) |
830 | return -EINVAL; | 838 | goto out; |
831 | 839 | ||
832 | retval = generic_write_checks(file, &pos, &count, 0); | 840 | retval = generic_write_checks(file, &pos, &count, 0); |
833 | if (retval) | 841 | if (retval) |