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>
This commit is contained in:
parent
b0afd8e5db
commit
b2de525f09
@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
|
||||
static const struct file_operations raw_fops = {
|
||||
.read = new_sync_read,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.read_iter = blkdev_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = blkdev_write_iter,
|
||||
.fsync = blkdev_fsync,
|
||||
|
@ -1585,7 +1585,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blkdev_write_iter);
|
||||
|
||||
static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
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)
|
||||
iov_iter_truncate(to, size);
|
||||
return generic_file_read_iter(iocb, to);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blkdev_read_iter);
|
||||
|
||||
/*
|
||||
* Try to release a page associated with block device when the system
|
||||
|
@ -2469,6 +2469,7 @@ extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
|
||||
extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
|
||||
|
||||
/* fs/block_dev.c */
|
||||
extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);
|
||||
extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from);
|
||||
extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
|
||||
int datasync);
|
||||
|
Loading…
Reference in New Issue
Block a user