@@ -297,6 +297,21 @@ static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
297297 return rv ;
298298}
299299
300+ static ssize_t proc_reg_read_iter (struct kiocb * iocb , struct iov_iter * iter )
301+ {
302+ struct proc_dir_entry * pde = PDE (file_inode (iocb -> ki_filp ));
303+ ssize_t ret ;
304+
305+ if (pde_is_permanent (pde ))
306+ return pde -> proc_ops -> proc_read_iter (iocb , iter );
307+
308+ if (!use_pde (pde ))
309+ return - EIO ;
310+ ret = pde -> proc_ops -> proc_read_iter (iocb , iter );
311+ unuse_pde (pde );
312+ return ret ;
313+ }
314+
300315static ssize_t pde_read (struct proc_dir_entry * pde , struct file * file , char __user * buf , size_t count , loff_t * ppos )
301316{
302317 typeof_member (struct proc_ops , proc_read ) read ;
@@ -578,6 +593,18 @@ static const struct file_operations proc_reg_file_ops = {
578593 .release = proc_reg_release ,
579594};
580595
596+ static const struct file_operations proc_iter_file_ops = {
597+ .llseek = proc_reg_llseek ,
598+ .read_iter = proc_reg_read_iter ,
599+ .write = proc_reg_write ,
600+ .poll = proc_reg_poll ,
601+ .unlocked_ioctl = proc_reg_unlocked_ioctl ,
602+ .mmap = proc_reg_mmap ,
603+ .get_unmapped_area = proc_reg_get_unmapped_area ,
604+ .open = proc_reg_open ,
605+ .release = proc_reg_release ,
606+ };
607+
581608#ifdef CONFIG_COMPAT
582609static const struct file_operations proc_reg_file_ops_compat = {
583610 .llseek = proc_reg_llseek ,
@@ -591,6 +618,19 @@ static const struct file_operations proc_reg_file_ops_compat = {
591618 .open = proc_reg_open ,
592619 .release = proc_reg_release ,
593620};
621+
622+ static const struct file_operations proc_iter_file_ops_compat = {
623+ .llseek = proc_reg_llseek ,
624+ .read_iter = proc_reg_read_iter ,
625+ .write = proc_reg_write ,
626+ .poll = proc_reg_poll ,
627+ .unlocked_ioctl = proc_reg_unlocked_ioctl ,
628+ .compat_ioctl = proc_reg_compat_ioctl ,
629+ .mmap = proc_reg_mmap ,
630+ .get_unmapped_area = proc_reg_get_unmapped_area ,
631+ .open = proc_reg_open ,
632+ .release = proc_reg_release ,
633+ };
594634#endif
595635
596636static void proc_put_link (void * p )
@@ -642,10 +682,17 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
642682
643683 if (S_ISREG (inode -> i_mode )) {
644684 inode -> i_op = de -> proc_iops ;
645- inode -> i_fop = & proc_reg_file_ops ;
685+ if (de -> proc_ops -> proc_read_iter )
686+ inode -> i_fop = & proc_iter_file_ops ;
687+ else
688+ inode -> i_fop = & proc_reg_file_ops ;
646689#ifdef CONFIG_COMPAT
647- if (de -> proc_ops -> proc_compat_ioctl )
648- inode -> i_fop = & proc_reg_file_ops_compat ;
690+ if (de -> proc_ops -> proc_compat_ioctl ) {
691+ if (de -> proc_ops -> proc_read_iter )
692+ inode -> i_fop = & proc_iter_file_ops_compat ;
693+ else
694+ inode -> i_fop = & proc_reg_file_ops_compat ;
695+ }
649696#endif
650697 } else if (S_ISDIR (inode -> i_mode )) {
651698 inode -> i_op = de -> proc_iops ;
0 commit comments