iov_iter_truncate()

Now It Can Be Done(tm) - we don't need to do iov_shorten() in
generic_file_direct_write() anymore, now that all ->direct_IO()
instances are converted to proper iov_iter methods and honour
iter->count and iter->iov_offset properly.

Get rid of count/ocount arguments of generic_file_direct_write(),
while we are at it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2014-03-22 06:51:37 -04:00
parent 28060d5d9b
commit 0c949334a9
7 changed files with 40 additions and 42 deletions

View File

@ -1659,8 +1659,7 @@ again:
static ssize_t __btrfs_direct_write(struct kiocb *iocb, static ssize_t __btrfs_direct_write(struct kiocb *iocb,
struct iov_iter *from, struct iov_iter *from,
loff_t pos, loff_t pos)
size_t count, size_t ocount)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
ssize_t written; ssize_t written;
@ -1668,9 +1667,9 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb,
loff_t endbyte; loff_t endbyte;
int err; int err;
written = generic_file_direct_write(iocb, from, pos, count, ocount); written = generic_file_direct_write(iocb, from, pos);
if (written < 0 || written == count) if (written < 0 || !iov_iter_count(from))
return written; return written;
pos += written; pos += written;
@ -1720,13 +1719,14 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
u64 end_pos; u64 end_pos;
ssize_t num_written = 0; ssize_t num_written = 0;
ssize_t err = 0; ssize_t err = 0;
size_t count, ocount; size_t count;
bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
struct iov_iter i; struct iov_iter i;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
count = ocount = iov_length(iov, nr_segs); count = iov_length(iov, nr_segs);
iov_iter_init(&i, WRITE, iov, nr_segs, count);
current->backing_dev_info = inode->i_mapping->backing_dev_info; current->backing_dev_info = inode->i_mapping->backing_dev_info;
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
@ -1740,7 +1740,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
goto out; goto out;
} }
iov_iter_init(&i, WRITE, iov, nr_segs, count); iov_iter_truncate(&i, count);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) { if (err) {
@ -1783,8 +1783,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
atomic_inc(&BTRFS_I(inode)->sync_writers); atomic_inc(&BTRFS_I(inode)->sync_writers);
if (unlikely(file->f_flags & O_DIRECT)) { if (unlikely(file->f_flags & O_DIRECT)) {
num_written = __btrfs_direct_write(iocb, &i, num_written = __btrfs_direct_write(iocb, &i, pos);
pos, count, ocount);
} else { } else {
num_written = __btrfs_buffered_write(file, &i, pos); num_written = __btrfs_buffered_write(file, &i, pos);
if (num_written > 0) if (num_written > 0)

View File

@ -1188,8 +1188,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
size_t count = 0; size_t count;
size_t ocount = 0;
ssize_t written = 0; ssize_t written = 0;
ssize_t written_buffered = 0; ssize_t written_buffered = 0;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
@ -1208,7 +1207,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
WARN_ON(iocb->ki_pos != pos); WARN_ON(iocb->ki_pos != pos);
count = ocount = iov_length(iov, nr_segs); count = iov_length(iov, nr_segs);
iov_iter_init(&i, WRITE, iov, nr_segs, count);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
/* We can write back this queue in page reclaim */ /* We can write back this queue in page reclaim */
@ -1217,11 +1217,11 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
if (err) if (err)
goto out; goto out;
iov_iter_init(&i, WRITE, iov, nr_segs, count);
if (count == 0) if (count == 0)
goto out; goto out;
iov_iter_truncate(&i, count);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) if (err)
goto out; goto out;
@ -1231,8 +1231,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
goto out; goto out;
if (file->f_flags & O_DIRECT) { if (file->f_flags & O_DIRECT) {
written = generic_file_direct_write(iocb, &i, pos, count, ocount); written = generic_file_direct_write(iocb, &i, pos);
if (written < 0 || written == count) if (written < 0 || !iov_iter_count(&i))
goto out; goto out;
pos += written; pos += written;
@ -1469,8 +1469,7 @@ static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
res = generic_write_checks(file, ppos, &count, 0); res = generic_write_checks(file, ppos, &count, 0);
if (!res) { if (!res) {
if (iter->count > count) iov_iter_truncate(iter, count);
iter->count = count;
res = fuse_direct_io(io, iter, ppos, FUSE_DIO_WRITE); res = fuse_direct_io(io, iter, ppos, FUSE_DIO_WRITE);
} }
@ -2896,8 +2895,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
if (offset >= i_size) if (offset >= i_size)
return 0; return 0;
count = min_t(loff_t, count, fuse_round_up(i_size - offset)); count = min_t(loff_t, count, fuse_round_up(i_size - offset));
if (iter->count > count) iov_iter_truncate(iter, count);
iter->count = count;
} }
io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL); io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);

View File

@ -2241,7 +2241,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
int ret, direct_io, appending, rw_level, have_alloc_sem = 0; int ret, direct_io, appending, rw_level, have_alloc_sem = 0;
int can_do_direct, has_refcount = 0; int can_do_direct, has_refcount = 0;
ssize_t written = 0; ssize_t written = 0;
size_t ocount; /* original count */
size_t count; /* after file limit checks */ size_t count; /* after file limit checks */
loff_t old_size, *ppos = &iocb->ki_pos; loff_t old_size, *ppos = &iocb->ki_pos;
u32 old_clusters; u32 old_clusters;
@ -2253,6 +2252,9 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
int unaligned_dio = 0; int unaligned_dio = 0;
struct iov_iter from; struct iov_iter from;
count = iov_length(iov, nr_segs);
iov_iter_init(&from, WRITE, iov, nr_segs, count);
trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry, trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
(unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)OCFS2_I(inode)->ip_blkno,
file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.len,
@ -2355,16 +2357,14 @@ relock:
/* communicate with ocfs2_dio_end_io */ /* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level); ocfs2_iocb_set_rw_locked(iocb, rw_level);
count = ocount = iov_length(iov, nr_segs);
ret = generic_write_checks(file, ppos, &count, ret = generic_write_checks(file, ppos, &count,
S_ISBLK(inode->i_mode)); S_ISBLK(inode->i_mode));
if (ret) if (ret)
goto out_dio; goto out_dio;
iov_iter_init(&from, WRITE, iov, nr_segs, count); iov_iter_truncate(&from, count);
if (direct_io) { if (direct_io) {
written = generic_file_direct_write(iocb, &from, *ppos, written = generic_file_direct_write(iocb, &from, *ppos);
count, ocount);
if (written < 0) { if (written < 0) {
ret = written; ret = written;
goto out_dio; goto out_dio;

View File

@ -626,7 +626,7 @@ xfs_file_dio_aio_write(
const struct iovec *iovp, const struct iovec *iovp,
unsigned long nr_segs, unsigned long nr_segs,
loff_t pos, loff_t pos,
size_t ocount) size_t count)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
@ -634,7 +634,6 @@ xfs_file_dio_aio_write(
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
ssize_t ret = 0; ssize_t ret = 0;
size_t count = ocount;
int unaligned_io = 0; int unaligned_io = 0;
int iolock; int iolock;
struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ? struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ?
@ -645,6 +644,8 @@ xfs_file_dio_aio_write(
if ((pos | count) & target->bt_logical_sectormask) if ((pos | count) & target->bt_logical_sectormask)
return -XFS_ERROR(EINVAL); return -XFS_ERROR(EINVAL);
iov_iter_init(&from, WRITE, iovp, nr_segs, count);
/* "unaligned" here means not aligned to a filesystem block */ /* "unaligned" here means not aligned to a filesystem block */
if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask)) if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
unaligned_io = 1; unaligned_io = 1;
@ -676,6 +677,7 @@ xfs_file_dio_aio_write(
ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock); ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
if (ret) if (ret)
goto out; goto out;
iov_iter_truncate(&from, count);
if (mapping->nrpages) { if (mapping->nrpages) {
ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
@ -697,8 +699,7 @@ xfs_file_dio_aio_write(
} }
trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0);
iov_iter_init(&from, WRITE, iovp, nr_segs, count); ret = generic_file_direct_write(iocb, &from, pos);
ret = generic_file_direct_write(iocb, &from, pos, count, ocount);
out: out:
xfs_rw_iunlock(ip, iolock); xfs_rw_iunlock(ip, iolock);

View File

@ -2407,8 +2407,7 @@ extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsig
extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long); extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long);
extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t); extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *, extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *, loff_t);
loff_t, size_t, size_t);
extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t); extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);

View File

@ -82,6 +82,12 @@ static inline size_t iov_iter_count(struct iov_iter *i)
return i->count; return i->count;
} }
static inline void iov_iter_truncate(struct iov_iter *i, size_t count)
{
if (i->count > count)
i->count = count;
}
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);

View File

@ -2345,8 +2345,7 @@ int pagecache_write_end(struct file *file, struct address_space *mapping,
EXPORT_SYMBOL(pagecache_write_end); EXPORT_SYMBOL(pagecache_write_end);
ssize_t ssize_t
generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from, generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos)
loff_t pos, size_t count, size_t ocount)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
@ -2356,10 +2355,7 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
pgoff_t end; pgoff_t end;
struct iov_iter data; struct iov_iter data;
if (count != ocount) write_len = iov_iter_count(from);
from->nr_segs = iov_shorten((struct iovec *)from->iov, from->nr_segs, count);
write_len = iov_length(from->iov, from->nr_segs);
end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT; end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1); written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);
@ -2568,7 +2564,6 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct address_space * mapping = file->f_mapping; struct address_space * mapping = file->f_mapping;
size_t ocount; /* original count */
size_t count; /* after file limit checks */ size_t count; /* after file limit checks */
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
loff_t pos = iocb->ki_pos; loff_t pos = iocb->ki_pos;
@ -2577,7 +2572,8 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
ssize_t status; ssize_t status;
struct iov_iter from; struct iov_iter from;
count = ocount = iov_length(iov, nr_segs); count = iov_length(iov, nr_segs);
iov_iter_init(&from, WRITE, iov, nr_segs, count);
/* We can write back this queue in page reclaim */ /* We can write back this queue in page reclaim */
current->backing_dev_info = mapping->backing_dev_info; current->backing_dev_info = mapping->backing_dev_info;
@ -2588,6 +2584,8 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (count == 0) if (count == 0)
goto out; goto out;
iov_iter_truncate(&from, count);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) if (err)
goto out; goto out;
@ -2596,14 +2594,11 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (err) if (err)
goto out; goto out;
iov_iter_init(&from, WRITE, iov, nr_segs, count);
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (unlikely(file->f_flags & O_DIRECT)) { if (unlikely(file->f_flags & O_DIRECT)) {
loff_t endbyte; loff_t endbyte;
written = generic_file_direct_write(iocb, &from, pos, written = generic_file_direct_write(iocb, &from, pos);
count, ocount);
if (written < 0 || written == count) if (written < 0 || written == count)
goto out; goto out;