18
18
#include <linux/mm.h>
19
19
#include <linux/printk.h>
20
20
#include <linux/string_helpers.h>
21
+ #include <linux/uio.h>
21
22
22
23
#include <linux/uaccess.h>
23
24
#include <asm/page.h>
@@ -146,7 +147,28 @@ static int traverse(struct seq_file *m, loff_t offset)
146
147
*/
147
148
ssize_t seq_read (struct file * file , char __user * buf , size_t size , loff_t * ppos )
148
149
{
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 );
150
172
size_t copied = 0 ;
151
173
size_t n ;
152
174
void * p ;
@@ -158,14 +180,14 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
158
180
* if request is to read from zero offset, reset iterator to first
159
181
* record as it might have been already advanced by previous requests
160
182
*/
161
- if (* ppos == 0 ) {
183
+ if (iocb -> ki_pos == 0 ) {
162
184
m -> index = 0 ;
163
185
m -> count = 0 ;
164
186
}
165
187
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 )
169
191
;
170
192
if (err ) {
171
193
/* With prejudice... */
@@ -174,7 +196,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
174
196
m -> count = 0 ;
175
197
goto Done ;
176
198
} else {
177
- m -> read_pos = * ppos ;
199
+ m -> read_pos = iocb -> ki_pos ;
178
200
}
179
201
}
180
202
@@ -187,13 +209,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
187
209
/* if not empty - flush it first */
188
210
if (m -> count ) {
189
211
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 )
192
213
goto Efault ;
193
214
m -> count -= n ;
194
215
m -> from += n ;
195
216
size -= n ;
196
- buf += n ;
197
217
copied += n ;
198
218
if (!size )
199
219
goto Done ;
@@ -254,8 +274,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
254
274
}
255
275
m -> op -> stop (m , p );
256
276
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 )
259
278
goto Efault ;
260
279
copied += n ;
261
280
m -> count -= n ;
@@ -264,7 +283,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
264
283
if (!copied )
265
284
copied = err ;
266
285
else {
267
- * ppos += copied ;
286
+ iocb -> ki_pos += copied ;
268
287
m -> read_pos += copied ;
269
288
}
270
289
mutex_unlock (& m -> lock );
@@ -276,7 +295,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
276
295
err = - EFAULT ;
277
296
goto Done ;
278
297
}
279
- EXPORT_SYMBOL (seq_read );
298
+ EXPORT_SYMBOL (seq_read_iter );
280
299
281
300
/**
282
301
* seq_lseek - ->llseek() method for sequential files.
0 commit comments