mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
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>
This commit is contained in:
parent
286d7d6a0c
commit
ce1a8e6796
@ -660,10 +660,10 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
|
|||||||
.iov_len = count,
|
.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_parent->d_name.name,
|
||||||
file->f_dentry->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))
|
if (!is_sync_kiocb(iocb))
|
||||||
goto out;
|
goto out;
|
||||||
@ -716,9 +716,7 @@ out:
|
|||||||
ssize_t
|
ssize_t
|
||||||
nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
|
nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
|
||||||
{
|
{
|
||||||
ssize_t retval = -EINVAL;
|
ssize_t retval;
|
||||||
loff_t *ppos = &iocb->ki_pos;
|
|
||||||
unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
|
||||||
struct file *file = iocb->ki_filp;
|
struct file *file = iocb->ki_filp;
|
||||||
struct nfs_open_context *ctx =
|
struct nfs_open_context *ctx =
|
||||||
(struct nfs_open_context *) file->private_data;
|
(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 inode *inode = mapping->host;
|
||||||
struct iovec iov = {
|
struct iovec iov = {
|
||||||
.iov_base = (char __user *)buf,
|
.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_parent->d_name.name,
|
||||||
file->f_dentry->d_name.name, inode->i_ino,
|
file->f_dentry->d_name.name,
|
||||||
(unsigned long) count, (unsigned long) pos);
|
(unsigned long) count, (long long) pos);
|
||||||
|
|
||||||
|
retval = -EINVAL;
|
||||||
if (!is_sync_kiocb(iocb))
|
if (!is_sync_kiocb(iocb))
|
||||||
goto out;
|
goto out;
|
||||||
if (count < 0)
|
|
||||||
|
retval = generic_write_checks(file, &pos, &count, 0);
|
||||||
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
if (pos < 0)
|
|
||||||
|
retval = -EINVAL;
|
||||||
|
if ((ssize_t) count < 0)
|
||||||
goto out;
|
goto out;
|
||||||
retval = -EFAULT;
|
|
||||||
if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
|
|
||||||
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;
|
retval = 0;
|
||||||
if (!count)
|
if (!count)
|
||||||
goto out;
|
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);
|
retval = nfs_sync_mapping(mapping);
|
||||||
if (retval)
|
if (retval)
|
||||||
@ -764,7 +759,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
|
|||||||
if (mapping->nrpages)
|
if (mapping->nrpages)
|
||||||
invalidate_inode_pages2(mapping);
|
invalidate_inode_pages2(mapping);
|
||||||
if (retval > 0)
|
if (retval > 0)
|
||||||
*ppos = pos + retval;
|
iocb->ki_pos = pos + retval;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
|
Loading…
Reference in New Issue
Block a user