diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-04-17 22:09:22 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-06 23:39:36 +0200 |
commit | 9b884164d59707216840159d45f6be68073fac6e (patch) | |
tree | c1e6f2ffef22003502bd8f118492b16ae03723bc /fs/ext4/file.c | |
parent | Merge ext4 changes in ext4_file_write() into for-next (diff) | |
download | linux-9b884164d59707216840159d45f6be68073fac6e.tar.xz linux-9b884164d59707216840159d45f6be68073fac6e.zip |
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 <peter.ujfalusi@ti.com> folded]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to '')
-rw-r--r-- | fs/ext4/file.c | 29 |
1 files changed, 11 insertions, 18 deletions
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, |