diff options
author | Chuck Lever <cel@netapp.com> | 2005-12-01 00:08:17 +0100 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-06 20:58:47 +0100 |
commit | ce1a8e6796150233f5098100f70217521dc7c08f (patch) | |
tree | 439d2abd246e051c43d1cdb7ee3b77b8864fd2b3 /fs/nfs/direct.c | |
parent | NFSv4: Remove requirement for machine creds for the "setclientid" operation (diff) | |
download | linux-ce1a8e6796150233f5098100f70217521dc7c08f.tar.xz linux-ce1a8e6796150233f5098100f70217521dc7c08f.zip |
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.c | 43 |
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 .iov_len = count, }; - dprintk("nfs: direct read(%s/%s, %lu@%lu)\n", + dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name, - (unsigned long) count, (unsigned long) pos); + (unsigned long) count, (long long) pos); if (!is_sync_kiocb(iocb)) goto out; @@ -716,9 +716,7 @@ out: ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) { - ssize_t retval = -EINVAL; - loff_t *ppos = &iocb->ki_pos; - unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; + ssize_t retval; struct file *file = iocb->ki_filp; struct nfs_open_context *ctx = (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, struct inode *inode = mapping->host; struct iovec iov = { .iov_base = (char __user *)buf, - .iov_len = count, }; - dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n", + dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, inode->i_ino, - (unsigned long) count, (unsigned long) pos); + file->f_dentry->d_name.name, + (unsigned long) count, (long long) pos); + retval = -EINVAL; if (!is_sync_kiocb(iocb)) goto out; - if (count < 0) - goto out; - if (pos < 0) + + retval = generic_write_checks(file, &pos, &count, 0); + if (retval) goto out; - retval = -EFAULT; - if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) + + retval = -EINVAL; + if ((ssize_t) count < 0) goto out; - retval = -EFBIG; - if (limit != RLIM_INFINITY) { - if (pos >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - if (count > limit - (unsigned long) pos) - count = limit - (unsigned long) pos; - } retval = 0; if (!count) goto out; + iov.iov_len = count, + + retval = -EFAULT; + if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) + goto out; retval = nfs_sync_mapping(mapping); if (retval) @@ -764,7 +759,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, if (mapping->nrpages) invalidate_inode_pages2(mapping); if (retval > 0) - *ppos = pos + retval; + iocb->ki_pos = pos + retval; out: return retval; |