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:
parent
28060d5d9b
commit
0c949334a9
@ -1659,8 +1659,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
|
||||
|
||||
static ssize_t __btrfs_direct_write(struct kiocb *iocb,
|
||||
struct iov_iter *from,
|
||||
loff_t pos,
|
||||
size_t count, size_t ocount)
|
||||
loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
ssize_t written;
|
||||
@ -1668,9 +1667,9 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb,
|
||||
loff_t endbyte;
|
||||
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;
|
||||
|
||||
pos += written;
|
||||
@ -1720,13 +1719,14 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||
u64 end_pos;
|
||||
ssize_t num_written = 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);
|
||||
struct iov_iter i;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
iov_iter_init(&i, WRITE, iov, nr_segs, count);
|
||||
iov_iter_truncate(&i, count);
|
||||
|
||||
err = file_remove_suid(file);
|
||||
if (err) {
|
||||
@ -1783,8 +1783,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||
atomic_inc(&BTRFS_I(inode)->sync_writers);
|
||||
|
||||
if (unlikely(file->f_flags & O_DIRECT)) {
|
||||
num_written = __btrfs_direct_write(iocb, &i,
|
||||
pos, count, ocount);
|
||||
num_written = __btrfs_direct_write(iocb, &i, pos);
|
||||
} else {
|
||||
num_written = __btrfs_buffered_write(file, &i, pos);
|
||||
if (num_written > 0)
|
||||
|
@ -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 address_space *mapping = file->f_mapping;
|
||||
size_t count = 0;
|
||||
size_t ocount = 0;
|
||||
size_t count;
|
||||
ssize_t written = 0;
|
||||
ssize_t written_buffered = 0;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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));
|
||||
if (err)
|
||||
goto out;
|
||||
iov_iter_init(&i, WRITE, iov, nr_segs, count);
|
||||
|
||||
if (count == 0)
|
||||
goto out;
|
||||
|
||||
iov_iter_truncate(&i, count);
|
||||
err = file_remove_suid(file);
|
||||
if (err)
|
||||
goto out;
|
||||
@ -1231,8 +1231,8 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
goto out;
|
||||
|
||||
if (file->f_flags & O_DIRECT) {
|
||||
written = generic_file_direct_write(iocb, &i, pos, count, ocount);
|
||||
if (written < 0 || written == count)
|
||||
written = generic_file_direct_write(iocb, &i, pos);
|
||||
if (written < 0 || !iov_iter_count(&i))
|
||||
goto out;
|
||||
|
||||
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);
|
||||
if (!res) {
|
||||
if (iter->count > count)
|
||||
iter->count = count;
|
||||
iov_iter_truncate(iter, count);
|
||||
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)
|
||||
return 0;
|
||||
count = min_t(loff_t, count, fuse_round_up(i_size - offset));
|
||||
if (iter->count > count)
|
||||
iter->count = count;
|
||||
iov_iter_truncate(iter, count);
|
||||
}
|
||||
|
||||
io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
|
||||
|
@ -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 can_do_direct, has_refcount = 0;
|
||||
ssize_t written = 0;
|
||||
size_t ocount; /* original count */
|
||||
size_t count; /* after file limit checks */
|
||||
loff_t old_size, *ppos = &iocb->ki_pos;
|
||||
u32 old_clusters;
|
||||
@ -2253,6 +2252,9 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
int unaligned_dio = 0;
|
||||
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,
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
file->f_path.dentry->d_name.len,
|
||||
@ -2355,16 +2357,14 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
/* communicate with ocfs2_dio_end_io */
|
||||
ocfs2_iocb_set_rw_locked(iocb, rw_level);
|
||||
|
||||
count = ocount = iov_length(iov, nr_segs);
|
||||
ret = generic_write_checks(file, ppos, &count,
|
||||
S_ISBLK(inode->i_mode));
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
iov_iter_init(&from, WRITE, iov, nr_segs, count);
|
||||
iov_iter_truncate(&from, count);
|
||||
if (direct_io) {
|
||||
written = generic_file_direct_write(iocb, &from, *ppos,
|
||||
count, ocount);
|
||||
written = generic_file_direct_write(iocb, &from, *ppos);
|
||||
if (written < 0) {
|
||||
ret = written;
|
||||
goto out_dio;
|
||||
|
@ -626,7 +626,7 @@ xfs_file_dio_aio_write(
|
||||
const struct iovec *iovp,
|
||||
unsigned long nr_segs,
|
||||
loff_t pos,
|
||||
size_t ocount)
|
||||
size_t count)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
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_mount *mp = ip->i_mount;
|
||||
ssize_t ret = 0;
|
||||
size_t count = ocount;
|
||||
int unaligned_io = 0;
|
||||
int iolock;
|
||||
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)
|
||||
return -XFS_ERROR(EINVAL);
|
||||
|
||||
iov_iter_init(&from, WRITE, iovp, nr_segs, count);
|
||||
|
||||
/* "unaligned" here means not aligned to a filesystem block */
|
||||
if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
|
||||
unaligned_io = 1;
|
||||
@ -676,6 +677,7 @@ xfs_file_dio_aio_write(
|
||||
ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock);
|
||||
if (ret)
|
||||
goto out;
|
||||
iov_iter_truncate(&from, count);
|
||||
|
||||
if (mapping->nrpages) {
|
||||
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);
|
||||
iov_iter_init(&from, WRITE, iovp, nr_segs, count);
|
||||
ret = generic_file_direct_write(iocb, &from, pos, count, ocount);
|
||||
ret = generic_file_direct_write(iocb, &from, pos);
|
||||
|
||||
out:
|
||||
xfs_rw_iunlock(ip, iolock);
|
||||
|
@ -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_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_direct_write(struct kiocb *, struct iov_iter *,
|
||||
loff_t, size_t, size_t);
|
||||
extern ssize_t generic_file_direct_write(struct kiocb *, 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_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
|
||||
|
@ -82,6 +82,12 @@ static inline size_t iov_iter_count(struct iov_iter *i)
|
||||
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_toiovec(struct iovec *iov, unsigned char *kdata, int len);
|
||||
|
||||
|
19
mm/filemap.c
19
mm/filemap.c
@ -2345,8 +2345,7 @@ int pagecache_write_end(struct file *file, struct address_space *mapping,
|
||||
EXPORT_SYMBOL(pagecache_write_end);
|
||||
|
||||
ssize_t
|
||||
generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
|
||||
loff_t pos, size_t count, size_t ocount)
|
||||
generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
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;
|
||||
struct iov_iter data;
|
||||
|
||||
if (count != ocount)
|
||||
from->nr_segs = iov_shorten((struct iovec *)from->iov, from->nr_segs, count);
|
||||
|
||||
write_len = iov_length(from->iov, from->nr_segs);
|
||||
write_len = iov_iter_count(from);
|
||||
end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
|
||||
|
||||
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 address_space * mapping = file->f_mapping;
|
||||
size_t ocount; /* original count */
|
||||
size_t count; /* after file limit checks */
|
||||
struct inode *inode = mapping->host;
|
||||
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;
|
||||
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 */
|
||||
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)
|
||||
goto out;
|
||||
|
||||
iov_iter_truncate(&from, count);
|
||||
|
||||
err = file_remove_suid(file);
|
||||
if (err)
|
||||
goto out;
|
||||
@ -2596,14 +2594,11 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
iov_iter_init(&from, WRITE, iov, nr_segs, count);
|
||||
|
||||
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
|
||||
if (unlikely(file->f_flags & O_DIRECT)) {
|
||||
loff_t endbyte;
|
||||
|
||||
written = generic_file_direct_write(iocb, &from, pos,
|
||||
count, ocount);
|
||||
written = generic_file_direct_write(iocb, &from, pos);
|
||||
if (written < 0 || written == count)
|
||||
goto out;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user