1818#include <linux/mm.h>
1919#include <linux/printk.h>
2020#include <linux/string_helpers.h>
21+ #include <linux/uio.h>
2122
2223#include <linux/uaccess.h>
2324#include <asm/page.h>
@@ -146,7 +147,28 @@ static int traverse(struct seq_file *m, loff_t offset)
146147 */
147148ssize_t seq_read (struct file * file , char __user * buf , size_t size , loff_t * ppos )
148149{
149- struct seq_file * m = file -> private_data ;
150+ struct iovec iov = { .iov_base = buf , .iov_len = size };
151+ struct kiocb kiocb ;
152+ struct iov_iter iter ;
153+ ssize_t ret ;
154+
155+ init_sync_kiocb (& kiocb , file );
156+ iov_iter_init (& iter , READ , & iov , 1 , size );
157+
158+ kiocb .ki_pos = * ppos ;
159+ ret = seq_read_iter (& kiocb , & iter );
160+ * ppos = kiocb .ki_pos ;
161+ return ret ;
162+ }
163+ EXPORT_SYMBOL (seq_read );
164+
165+ /*
166+ * Ready-made ->f_op->read_iter()
167+ */
168+ ssize_t seq_read_iter (struct kiocb * iocb , struct iov_iter * iter )
169+ {
170+ struct seq_file * m = iocb -> ki_filp -> private_data ;
171+ size_t size = iov_iter_count (iter );
150172 size_t copied = 0 ;
151173 size_t n ;
152174 void * p ;
@@ -158,14 +180,14 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
158180 * if request is to read from zero offset, reset iterator to first
159181 * record as it might have been already advanced by previous requests
160182 */
161- if (* ppos == 0 ) {
183+ if (iocb -> ki_pos == 0 ) {
162184 m -> index = 0 ;
163185 m -> count = 0 ;
164186 }
165187
166- /* Don't assume *ppos is where we left it */
167- if (unlikely (* ppos != m -> read_pos )) {
168- while ((err = traverse (m , * ppos )) == - EAGAIN )
188+ /* Don't assume ki_pos is where we left it */
189+ if (unlikely (iocb -> ki_pos != m -> read_pos )) {
190+ while ((err = traverse (m , iocb -> ki_pos )) == - EAGAIN )
169191 ;
170192 if (err ) {
171193 /* With prejudice... */
@@ -174,7 +196,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
174196 m -> count = 0 ;
175197 goto Done ;
176198 } else {
177- m -> read_pos = * ppos ;
199+ m -> read_pos = iocb -> ki_pos ;
178200 }
179201 }
180202
@@ -187,13 +209,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
187209 /* if not empty - flush it first */
188210 if (m -> count ) {
189211 n = min (m -> count , size );
190- err = copy_to_user (buf , m -> buf + m -> from , n );
191- if (err )
212+ if (copy_to_iter (m -> buf + m -> from , n , iter ) != n )
192213 goto Efault ;
193214 m -> count -= n ;
194215 m -> from += n ;
195216 size -= n ;
196- buf += n ;
197217 copied += n ;
198218 if (!size )
199219 goto Done ;
@@ -254,8 +274,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
254274 }
255275 m -> op -> stop (m , p );
256276 n = min (m -> count , size );
257- err = copy_to_user (buf , m -> buf , n );
258- if (err )
277+ if (copy_to_iter (m -> buf , n , iter ) != n )
259278 goto Efault ;
260279 copied += n ;
261280 m -> count -= n ;
@@ -264,7 +283,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
264283 if (!copied )
265284 copied = err ;
266285 else {
267- * ppos += copied ;
286+ iocb -> ki_pos += copied ;
268287 m -> read_pos += copied ;
269288 }
270289 mutex_unlock (& m -> lock );
@@ -276,7 +295,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
276295 err = - EFAULT ;
277296 goto Done ;
278297}
279- EXPORT_SYMBOL (seq_read );
298+ EXPORT_SYMBOL (seq_read_iter );
280299
281300/**
282301 * seq_lseek - ->llseek() method for sequential files.
0 commit comments