aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2005-11-30 18:08:17 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:47 -0500
commitce1a8e6796150233f5098100f70217521dc7c08f (patch)
tree439d2abd246e051c43d1cdb7ee3b77b8864fd2b3 /fs/nfs/direct.c
parent286d7d6a0cb38d3d4316a1dfea9b0c0fc5a6455b (diff)
NFS: use generic_write_checks() to sanity check direct writes
Replace ad hoc write parameter sanity checking in nfs_file_direct_write() with a call to generic_write_checks(). This should make the proper checks modulo the O_LARGEFILE flag, and should catch NFSv2-specific limitations by virtue of i_sb->s_maxbytes. Test plan: Posix compliance testing with both NFSv2 and NFSv3. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r--fs/nfs/direct.c43
1 files changed, 19 insertions, 24 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index ae2be0744191..f69d95aa78b2 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -660,10 +660,10 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
660 .iov_len = count, 660 .iov_len = count,
661 }; 661 };
662 662
663 dprintk("nfs: direct read(%s/%s, %lu@%lu)\n", 663 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
664 file->f_dentry->d_parent->d_name.name, 664 file->f_dentry->d_parent->d_name.name,
665 file->f_dentry->d_name.name, 665 file->f_dentry->d_name.name,
666 (unsigned long) count, (unsigned long) pos); 666 (unsigned long) count, (long long) pos);
667 667
668 if (!is_sync_kiocb(iocb)) 668 if (!is_sync_kiocb(iocb))
669 goto out; 669 goto out;
@@ -716,9 +716,7 @@ out:
716ssize_t 716ssize_t
717nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) 717nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
718{ 718{
719 ssize_t retval = -EINVAL; 719 ssize_t retval;
720 loff_t *ppos = &iocb->ki_pos;
721 unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
722 struct file *file = iocb->ki_filp; 720 struct file *file = iocb->ki_filp;
723 struct nfs_open_context *ctx = 721 struct nfs_open_context *ctx =
724 (struct nfs_open_context *) file->private_data; 722 (struct nfs_open_context *) file->private_data;
@@ -726,35 +724,32 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
726 struct inode *inode = mapping->host; 724 struct inode *inode = mapping->host;
727 struct iovec iov = { 725 struct iovec iov = {
728 .iov_base = (char __user *)buf, 726 .iov_base = (char __user *)buf,
729 .iov_len = count,
730 }; 727 };
731 728
732 dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n", 729 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
733 file->f_dentry->d_parent->d_name.name, 730 file->f_dentry->d_parent->d_name.name,
734 file->f_dentry->d_name.name, inode->i_ino, 731 file->f_dentry->d_name.name,
735 (unsigned long) count, (unsigned long) pos); 732 (unsigned long) count, (long long) pos);
736 733
734 retval = -EINVAL;
737 if (!is_sync_kiocb(iocb)) 735 if (!is_sync_kiocb(iocb))
738 goto out; 736 goto out;
739 if (count < 0) 737
740 goto out; 738 retval = generic_write_checks(file, &pos, &count, 0);
741 if (pos < 0) 739 if (retval)
742 goto out; 740 goto out;
743 retval = -EFAULT; 741
744 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) 742 retval = -EINVAL;
743 if ((ssize_t) count < 0)
745 goto out; 744 goto out;
746 retval = -EFBIG;
747 if (limit != RLIM_INFINITY) {
748 if (pos >= limit) {
749 send_sig(SIGXFSZ, current, 0);
750 goto out;
751 }
752 if (count > limit - (unsigned long) pos)
753 count = limit - (unsigned long) pos;
754 }
755 retval = 0; 745 retval = 0;
756 if (!count) 746 if (!count)
757 goto out; 747 goto out;
748 iov.iov_len = count,
749
750 retval = -EFAULT;
751 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
752 goto out;
758 753
759 retval = nfs_sync_mapping(mapping); 754 retval = nfs_sync_mapping(mapping);
760 if (retval) 755 if (retval)
@@ -764,7 +759,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
764 if (mapping->nrpages) 759 if (mapping->nrpages)
765 invalidate_inode_pages2(mapping); 760 invalidate_inode_pages2(mapping);
766 if (retval > 0) 761 if (retval > 0)
767 *ppos = pos + retval; 762 iocb->ki_pos = pos + retval;
768 763
769out: 764out:
770 return retval; 765 return retval;