aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r--fs/nfs/direct.c81
1 files changed, 32 insertions, 49 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index b497c71384e8..10ae377e68ff 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -122,9 +122,10 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
122{ 122{
123 int i; 123 int i;
124 for (i = 0; i < npages; i++) { 124 for (i = 0; i < npages; i++) {
125 if (do_dirty) 125 struct page *page = pages[i];
126 set_page_dirty_lock(pages[i]); 126 if (do_dirty && !PageCompound(page))
127 page_cache_release(pages[i]); 127 set_page_dirty_lock(page);
128 page_cache_release(page);
128 } 129 }
129 kfree(pages); 130 kfree(pages);
130} 131}
@@ -154,6 +155,7 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int
154 struct list_head *list; 155 struct list_head *list;
155 struct nfs_direct_req *dreq; 156 struct nfs_direct_req *dreq;
156 unsigned int reads = 0; 157 unsigned int reads = 0;
158 unsigned int rpages = (rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
157 159
158 dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL); 160 dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL);
159 if (!dreq) 161 if (!dreq)
@@ -167,7 +169,7 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int
167 169
168 list = &dreq->list; 170 list = &dreq->list;
169 for(;;) { 171 for(;;) {
170 struct nfs_read_data *data = nfs_readdata_alloc(); 172 struct nfs_read_data *data = nfs_readdata_alloc(rpages);
171 173
172 if (unlikely(!data)) { 174 if (unlikely(!data)) {
173 while (!list_empty(list)) { 175 while (!list_empty(list)) {
@@ -268,8 +270,6 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
268 NFS_PROTO(inode)->read_setup(data); 270 NFS_PROTO(inode)->read_setup(data);
269 271
270 data->task.tk_cookie = (unsigned long) inode; 272 data->task.tk_cookie = (unsigned long) inode;
271 data->task.tk_calldata = data;
272 data->task.tk_release = nfs_readdata_release;
273 data->complete = nfs_direct_read_result; 273 data->complete = nfs_direct_read_result;
274 274
275 lock_kernel(); 275 lock_kernel();
@@ -433,7 +433,7 @@ static ssize_t nfs_direct_write_seg(struct inode *inode,
433 struct nfs_writeverf first_verf; 433 struct nfs_writeverf first_verf;
434 struct nfs_write_data *wdata; 434 struct nfs_write_data *wdata;
435 435
436 wdata = nfs_writedata_alloc(); 436 wdata = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
437 if (!wdata) 437 if (!wdata)
438 return -ENOMEM; 438 return -ENOMEM;
439 439
@@ -662,10 +662,10 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
662 .iov_len = count, 662 .iov_len = count,
663 }; 663 };
664 664
665 dprintk("nfs: direct read(%s/%s, %lu@%lu)\n", 665 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
666 file->f_dentry->d_parent->d_name.name, 666 file->f_dentry->d_parent->d_name.name,
667 file->f_dentry->d_name.name, 667 file->f_dentry->d_name.name,
668 (unsigned long) count, (unsigned long) pos); 668 (unsigned long) count, (long long) pos);
669 669
670 if (!is_sync_kiocb(iocb)) 670 if (!is_sync_kiocb(iocb))
671 goto out; 671 goto out;
@@ -678,15 +678,9 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
678 if (!count) 678 if (!count)
679 goto out; 679 goto out;
680 680
681 if (mapping->nrpages) { 681 retval = nfs_sync_mapping(mapping);
682 retval = filemap_fdatawrite(mapping); 682 if (retval)
683 if (retval == 0) 683 goto out;
684 retval = nfs_wb_all(inode);
685 if (retval == 0)
686 retval = filemap_fdatawait(mapping);
687 if (retval)
688 goto out;
689 }
690 684
691 retval = nfs_direct_read(inode, ctx, &iov, pos, 1); 685 retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
692 if (retval > 0) 686 if (retval > 0)
@@ -724,9 +718,7 @@ out:
724ssize_t 718ssize_t
725nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) 719nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
726{ 720{
727 ssize_t retval = -EINVAL; 721 ssize_t retval;
728 loff_t *ppos = &iocb->ki_pos;
729 unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
730 struct file *file = iocb->ki_filp; 722 struct file *file = iocb->ki_filp;
731 struct nfs_open_context *ctx = 723 struct nfs_open_context *ctx =
732 (struct nfs_open_context *) file->private_data; 724 (struct nfs_open_context *) file->private_data;
@@ -734,51 +726,42 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
734 struct inode *inode = mapping->host; 726 struct inode *inode = mapping->host;
735 struct iovec iov = { 727 struct iovec iov = {
736 .iov_base = (char __user *)buf, 728 .iov_base = (char __user *)buf,
737 .iov_len = count,
738 }; 729 };
739 730
740 dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n", 731 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
741 file->f_dentry->d_parent->d_name.name, 732 file->f_dentry->d_parent->d_name.name,
742 file->f_dentry->d_name.name, inode->i_ino, 733 file->f_dentry->d_name.name,
743 (unsigned long) count, (unsigned long) pos); 734 (unsigned long) count, (long long) pos);
744 735
736 retval = -EINVAL;
745 if (!is_sync_kiocb(iocb)) 737 if (!is_sync_kiocb(iocb))
746 goto out; 738 goto out;
747 if (count < 0) 739
748 goto out; 740 retval = generic_write_checks(file, &pos, &count, 0);
749 if (pos < 0) 741 if (retval)
750 goto out; 742 goto out;
751 retval = -EFAULT; 743
752 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) 744 retval = -EINVAL;
745 if ((ssize_t) count < 0)
753 goto out; 746 goto out;
754 retval = -EFBIG;
755 if (limit != RLIM_INFINITY) {
756 if (pos >= limit) {
757 send_sig(SIGXFSZ, current, 0);
758 goto out;
759 }
760 if (count > limit - (unsigned long) pos)
761 count = limit - (unsigned long) pos;
762 }
763 retval = 0; 747 retval = 0;
764 if (!count) 748 if (!count)
765 goto out; 749 goto out;
750 iov.iov_len = count,
766 751
767 if (mapping->nrpages) { 752 retval = -EFAULT;
768 retval = filemap_fdatawrite(mapping); 753 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
769 if (retval == 0) 754 goto out;
770 retval = nfs_wb_all(inode); 755
771 if (retval == 0) 756 retval = nfs_sync_mapping(mapping);
772 retval = filemap_fdatawait(mapping); 757 if (retval)
773 if (retval) 758 goto out;
774 goto out;
775 }
776 759
777 retval = nfs_direct_write(inode, ctx, &iov, pos, 1); 760 retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
778 if (mapping->nrpages) 761 if (mapping->nrpages)
779 invalidate_inode_pages2(mapping); 762 invalidate_inode_pages2(mapping);
780 if (retval > 0) 763 if (retval > 0)
781 *ppos = pos + retval; 764 iocb->ki_pos = pos + retval;
782 765
783out: 766out:
784 return retval; 767 return retval;