From d8d3d94b80aa1a1c0ca75c58b8abdc7356f38418 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Mar 2014 21:27:34 -0500 Subject: pass iov_iter to ->direct_IO() unmodified, for now Signed-off-by: Al Viro --- fs/ext4/inode.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d7b7462a0e13..f51db730da39 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3222,8 +3222,7 @@ retake_lock: } static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, - unsigned long nr_segs) + struct iov_iter *iter, loff_t offset) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; @@ -3239,13 +3238,13 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, if (ext4_has_inline_data(inode)) return 0; - trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw); + trace_ext4_direct_IO_enter(inode, offset, iov_length(iter->iov, iter->nr_segs), rw); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); + ret = ext4_ext_direct_IO(rw, iocb, iter->iov, offset, iter->nr_segs); else - ret = ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); + ret = ext4_ind_direct_IO(rw, iocb, iter->iov, offset, iter->nr_segs); trace_ext4_direct_IO_exit(inode, offset, - iov_length(iov, nr_segs), rw, ret); + iov_length(iter->iov, iter->nr_segs), rw, ret); return ret; } -- cgit v1.2.1 From 16b1f05d7f5ab4ce570963aca5f3b2b5d21822fa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Mar 2014 22:14:00 -0500 Subject: ext4: switch the guts of ->direct_IO() to iov_iter Signed-off-by: Al Viro --- fs/ext4/ext4.h | 3 +-- fs/ext4/indirect.c | 15 +++++++-------- fs/ext4/inode.c | 15 +++++++-------- 3 files changed, 15 insertions(+), 18 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 66946aa62127..9334f55dab6f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2150,8 +2150,7 @@ extern void ext4_da_update_reserve_space(struct inode *inode, extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags); extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, - unsigned long nr_segs); + struct iov_iter *iter, loff_t offset); extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock); extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks); extern void ext4_ind_truncate(handle_t *, struct inode *inode); diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 594009f5f523..eb5ae16902d0 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -639,8 +639,7 @@ out: * VFS code falls back into buffered path in that case so we are safe. */ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, - unsigned long nr_segs) + struct iov_iter *iter, loff_t offset) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; @@ -648,7 +647,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, handle_t *handle; ssize_t ret; int orphan = 0; - size_t count = iov_length(iov, nr_segs); + size_t count = iov_length(iter->iov, iter->nr_segs); int retries = 0; if (rw == WRITE) { @@ -687,18 +686,18 @@ retry: goto locked; } ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, + inode->i_sb->s_bdev, iter->iov, + offset, iter->nr_segs, ext4_get_block, NULL, NULL, 0); inode_dio_done(inode); } else { locked: - ret = blockdev_direct_IO(rw, iocb, inode, iov, - offset, nr_segs, ext4_get_block); + ret = blockdev_direct_IO(rw, iocb, inode, iter->iov, + offset, iter->nr_segs, ext4_get_block); if (unlikely((rw & WRITE) && ret < 0)) { loff_t isize = i_size_read(inode); - loff_t end = offset + iov_length(iov, nr_segs); + loff_t end = offset + count; if (end > isize) ext4_truncate_failed_write(inode); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f51db730da39..29996c1b673e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3085,13 +3085,12 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, * */ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, - unsigned long nr_segs) + struct iov_iter *iter, loff_t offset) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; ssize_t ret; - size_t count = iov_length(iov, nr_segs); + size_t count = iov_length(iter->iov, iter->nr_segs); int overwrite = 0; get_block_t *get_block_func = NULL; int dio_flags = 0; @@ -3100,7 +3099,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, /* Use the old path for reads and writes beyond i_size. */ if (rw != WRITE || final_size > inode->i_size) - return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); + return ext4_ind_direct_IO(rw, iocb, iter, offset); BUG_ON(iocb->private == NULL); @@ -3167,8 +3166,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, dio_flags = DIO_LOCKING; } ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, + inode->i_sb->s_bdev, iter->iov, + offset, iter->nr_segs, get_block_func, ext4_end_io_dio, NULL, @@ -3240,9 +3239,9 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, trace_ext4_direct_IO_enter(inode, offset, iov_length(iter->iov, iter->nr_segs), rw); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - ret = ext4_ext_direct_IO(rw, iocb, iter->iov, offset, iter->nr_segs); + ret = ext4_ext_direct_IO(rw, iocb, iter, offset); else - ret = ext4_ind_direct_IO(rw, iocb, iter->iov, offset, iter->nr_segs); + ret = ext4_ind_direct_IO(rw, iocb, iter, offset); trace_ext4_direct_IO_exit(inode, offset, iov_length(iter->iov, iter->nr_segs), rw, ret); return ret; -- cgit v1.2.1 From a6cbcd4a4a85e2fdb0b3344b88df2e8b3d526b9e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Mar 2014 22:38:00 -0500 Subject: get rid of pointless iov_length() in ->direct_IO() all callers have iov_length(iter->iov, iter->nr_segs) == iov_iter_count(iter) Signed-off-by: Al Viro --- fs/ext4/indirect.c | 2 +- fs/ext4/inode.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index eb5ae16902d0..123898a6af05 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -647,7 +647,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, handle_t *handle; ssize_t ret; int orphan = 0; - size_t count = iov_length(iter->iov, iter->nr_segs); + size_t count = iov_iter_count(iter); int retries = 0; if (rw == WRITE) { diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 29996c1b673e..2b993579a968 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3090,7 +3090,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; ssize_t ret; - size_t count = iov_length(iter->iov, iter->nr_segs); + size_t count = iov_iter_count(iter); int overwrite = 0; get_block_t *get_block_func = NULL; int dio_flags = 0; @@ -3225,6 +3225,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + size_t count = iov_iter_count(iter); ssize_t ret; /* @@ -3237,13 +3238,12 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, if (ext4_has_inline_data(inode)) return 0; - trace_ext4_direct_IO_enter(inode, offset, iov_length(iter->iov, iter->nr_segs), rw); + trace_ext4_direct_IO_enter(inode, offset, count, rw); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) ret = ext4_ext_direct_IO(rw, iocb, iter, offset); else ret = ext4_ind_direct_IO(rw, iocb, iter, offset); - trace_ext4_direct_IO_exit(inode, offset, - iov_length(iter->iov, iter->nr_segs), rw, ret); + trace_ext4_direct_IO_exit(inode, offset, count, rw, ret); return ret; } -- cgit v1.2.1 From 31b140398ce56ab41646eda7f02bcb78d6a4c916 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Mar 2014 01:33:16 -0500 Subject: switch {__,}blockdev_direct_IO() to iov_iter Signed-off-by: Al Viro --- fs/ext4/indirect.c | 7 +++---- fs/ext4/inode.c | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 123898a6af05..8a57e9fcd1b9 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -686,14 +686,13 @@ retry: goto locked; } ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iter->iov, - offset, iter->nr_segs, + inode->i_sb->s_bdev, iter, offset, ext4_get_block, NULL, NULL, 0); inode_dio_done(inode); } else { locked: - ret = blockdev_direct_IO(rw, iocb, inode, iter->iov, - offset, iter->nr_segs, ext4_get_block); + ret = blockdev_direct_IO(rw, iocb, inode, iter, + offset, ext4_get_block); if (unlikely((rw & WRITE) && ret < 0)) { loff_t isize = i_size_read(inode); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2b993579a968..e5718385a037 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3166,8 +3166,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, dio_flags = DIO_LOCKING; } ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iter->iov, - offset, iter->nr_segs, + inode->i_sb->s_bdev, iter, + offset, get_block_func, ext4_end_io_dio, NULL, -- cgit v1.2.1 From aad4f8bb42af06371aa0e85bf0cd9d52c0494985 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 Apr 2014 14:33:16 -0400 Subject: switch simple generic_file_aio_read() users to ->read_iter() Signed-off-by: Al Viro --- fs/ext4/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 063fc1538355..881394280d5f 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -593,9 +593,9 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int whence) const struct file_operations ext4_file_operations = { .llseek = ext4_llseek, - .read = do_sync_read, + .read = new_sync_read, .write = do_sync_write, - .aio_read = generic_file_aio_read, + .read_iter = generic_file_read_iter, .aio_write = ext4_file_write, .unlocked_ioctl = ext4_ioctl, #ifdef CONFIG_COMPAT -- cgit v1.2.1 From 9b884164d59707216840159d45f6be68073fac6e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 17 Apr 2014 16:09:22 -0400 Subject: convert ext4 to ->write_iter() unfortunately, Ted's changes to ext4_file_write() are *still* an incomplete fix - playing with rlimits can let you smuggle an unaligned request past the checks. So there almost certainly will be more merge PITA around that place... [fix from Peter Ujfalusi folded] Signed-off-by: Al Viro --- fs/ext4/file.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 86a13a514e4a..48383a5f37a1 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -74,26 +74,22 @@ void ext4_unwritten_wait(struct inode *inode) * or one thread will zero the other's data, causing corruption. */ static int -ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos) { struct super_block *sb = inode->i_sb; int blockmask = sb->s_blocksize - 1; - size_t count = iov_length(iov, nr_segs); - loff_t final_size = pos + count; if (pos >= i_size_read(inode)) return 0; - if ((pos & blockmask) || (final_size & blockmask)) + if ((pos | iov_iter_alignment(from)) & blockmask) return 1; return 0; } static ssize_t -ext4_file_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *inode = file_inode(iocb->ki_filp); @@ -101,10 +97,9 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, struct blk_plug plug; int o_direct = file->f_flags & O_DIRECT; int overwrite = 0; - size_t length = iov_length(iov, nr_segs); + size_t length = iov_iter_count(from); ssize_t ret; - - BUG_ON(iocb->ki_pos != pos); + loff_t pos = iocb->ki_pos; /* * Unaligned direct AIO must be serialized; see comment above @@ -114,7 +109,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && !is_sync_kiocb(iocb) && (file->f_flags & O_APPEND || - ext4_unaligned_aio(inode, iov, nr_segs, pos))) { + ext4_unaligned_aio(inode, from, pos))) { aio_mutex = ext4_aio_mutex(inode); mutex_lock(aio_mutex); ext4_unwritten_wait(inode); @@ -138,10 +133,8 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, goto errout; } - if (pos + length > sbi->s_bitmap_maxbytes) { - nr_segs = iov_shorten((struct iovec *)iov, nr_segs, - sbi->s_bitmap_maxbytes - pos); - } + if (pos + length > sbi->s_bitmap_maxbytes) + iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos); } if (o_direct) { @@ -179,7 +172,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, } } - ret = __generic_file_aio_write(iocb, iov, nr_segs); + ret = __generic_file_write_iter(iocb, from); mutex_unlock(&inode->i_mutex); if (ret > 0) { @@ -594,9 +587,9 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int whence) const struct file_operations ext4_file_operations = { .llseek = ext4_llseek, .read = new_sync_read, - .write = do_sync_write, + .write = new_sync_write, .read_iter = generic_file_read_iter, - .aio_write = ext4_file_write, + .write_iter = ext4_file_write_iter, .unlocked_ioctl = ext4_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext4_compat_ioctl, -- cgit v1.2.1 From 8d0207652cbe27d1f962050737848e5ad4671958 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 5 Apr 2014 04:27:08 -0400 Subject: ->splice_write() via ->write_iter() iter_file_splice_write() - a ->splice_write() instance that gathers the pipe buffers, builds a bio_vec-based iov_iter covering those and feeds it to ->write_iter(). A bunch of simple cases coverted to that... [AV: fixed the braino spotted by Cyrill] Signed-off-by: Al Viro --- fs/ext4/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext4') diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 48383a5f37a1..708aad768199 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -599,7 +599,7 @@ const struct file_operations ext4_file_operations = { .release = ext4_release_file, .fsync = ext4_sync_file, .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, + .splice_write = iter_file_splice_write, .fallocate = ext4_fallocate, }; -- cgit v1.2.1