This will allow proc files to implement iter read semantics. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- fs/proc/inode.c | 28 ++++++++++++++++++++++++++++ include/linux/proc_fs.h | 1 + 2 files changed, 29 insertions(+) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 28d6105e908e4c..fa86619cebc2be 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -297,6 +297,29 @@ static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence) return rv; } +static ssize_t pde_read_iter(struct proc_dir_entry *pde, struct kiocb *iocb, + struct iov_iter *iter) +{ + if (!pde->proc_ops->proc_read_iter) + return -EINVAL; + return pde->proc_ops->proc_read_iter(iocb, iter); +} + +static ssize_t proc_reg_read_iter(struct kiocb *iocb, struct iov_iter *iter) +{ + struct proc_dir_entry *pde = PDE(file_inode(iocb->ki_filp)); + ssize_t ret; + + if (pde_is_permanent(pde)) + return pde_read_iter(pde, iocb, iter); + + if (!use_pde(pde)) + return -EIO; + ret = pde_read_iter(pde, iocb, iter); + unuse_pde(pde); + return ret; +} + static ssize_t pde_read(struct proc_dir_entry *pde, struct file *file, char __user *buf, size_t count, loff_t *ppos) { typeof_member(struct proc_ops, proc_read) read; @@ -312,6 +335,9 @@ static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, struct proc_dir_entry *pde = PDE(file_inode(file)); ssize_t rv = -EIO; + if (pde->proc_ops->proc_read_iter) + return iter_read(file, buf, count, ppos, proc_reg_read_iter); + if (pde_is_permanent(pde)) { return pde_read(pde, file, buf, count, ppos); } else if (use_pde(pde)) { @@ -569,6 +595,7 @@ static int proc_reg_release(struct inode *inode, struct file *file) static const struct file_operations proc_reg_file_ops = { .llseek = proc_reg_llseek, .read = proc_reg_read, + .read_iter = proc_reg_read_iter, .write = proc_reg_write, .poll = proc_reg_poll, .unlocked_ioctl = proc_reg_unlocked_ioctl, @@ -585,6 +612,7 @@ static const struct file_operations proc_reg_file_ops = { static const struct file_operations proc_reg_file_ops_no_compat = { .llseek = proc_reg_llseek, .read = proc_reg_read, + .read_iter = proc_reg_read_iter, .write = proc_reg_write, .poll = proc_reg_poll, .unlocked_ioctl = proc_reg_unlocked_ioctl, diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index d1eed1b4365172..97b3f5f06db9d8 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -30,6 +30,7 @@ struct proc_ops { unsigned int proc_flags; int (*proc_open)(struct inode *, struct file *); ssize_t (*proc_read)(struct file *, char __user *, size_t, loff_t *); + ssize_t (*proc_read_iter)(struct kiocb *, struct iov_iter *); ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *); loff_t (*proc_lseek)(struct file *, loff_t, int); int (*proc_release)(struct inode *, struct file *); -- 2.26.2