aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Jeffery <djeffery@redhat.com>2014-09-29 10:21:10 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-10-31 06:33:26 -0400
commitb2de525f095708b2adbadaec3f1e4017a23d1e09 (patch)
tree4a46a47864031b2a019d6fa605d835a3ca88c539
parentb0afd8e5db7b11aa9078e82e7f9abc30dc35a3c1 (diff)
Return short read or 0 at end of a raw device, not EIO
Author: David Jeffery <djeffery@redhat.com> Changes to the basic direct I/O code have broken the raw driver when reading to the end of a raw device. Instead of returning a short read for a read that extends partially beyond the device's end or 0 when at the end of the device, these reads now return EIO. The raw driver needs the same end of device handling as was added for normal block devices. Using blkdev_read_iter, which has the needed size checks, prevents the EIO conditions at the end of the device. Signed-off-by: David Jeffery <djeffery@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--drivers/char/raw.c2
-rw-r--r--fs/block_dev.c3
-rw-r--r--include/linux/fs.h1
3 files changed, 4 insertions, 2 deletions
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 0102dc788608..a24891b97547 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
285 285
286static const struct file_operations raw_fops = { 286static const struct file_operations raw_fops = {
287 .read = new_sync_read, 287 .read = new_sync_read,
288 .read_iter = generic_file_read_iter, 288 .read_iter = blkdev_read_iter,
289 .write = new_sync_write, 289 .write = new_sync_write,
290 .write_iter = blkdev_write_iter, 290 .write_iter = blkdev_write_iter,
291 .fsync = blkdev_fsync, 291 .fsync = blkdev_fsync,
diff --git a/fs/block_dev.c b/fs/block_dev.c
index cc9d4114cda0..1d9c9f3754f8 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1585,7 +1585,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
1585} 1585}
1586EXPORT_SYMBOL_GPL(blkdev_write_iter); 1586EXPORT_SYMBOL_GPL(blkdev_write_iter);
1587 1587
1588static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) 1588ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
1589{ 1589{
1590 struct file *file = iocb->ki_filp; 1590 struct file *file = iocb->ki_filp;
1591 struct inode *bd_inode = file->f_mapping->host; 1591 struct inode *bd_inode = file->f_mapping->host;
@@ -1599,6 +1599,7 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
1599 iov_iter_truncate(to, size); 1599 iov_iter_truncate(to, size);
1600 return generic_file_read_iter(iocb, to); 1600 return generic_file_read_iter(iocb, to);
1601} 1601}
1602EXPORT_SYMBOL_GPL(blkdev_read_iter);
1602 1603
1603/* 1604/*
1604 * Try to release a page associated with block device when the system 1605 * Try to release a page associated with block device when the system
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 01036262095f..9ab779e8a63c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2469,6 +2469,7 @@ extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
2469extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); 2469extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
2470 2470
2471/* fs/block_dev.c */ 2471/* fs/block_dev.c */
2472extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);
2472extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from); 2473extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from);
2473extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, 2474extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
2474 int datasync); 2475 int datasync);