@@ -168,12 +168,14 @@ EXPORT_SYMBOL(seq_read);
168
168
ssize_t seq_read_iter (struct kiocb * iocb , struct iov_iter * iter )
169
169
{
170
170
struct seq_file * m = iocb -> ki_filp -> private_data ;
171
- size_t size = iov_iter_count (iter );
172
171
size_t copied = 0 ;
173
172
size_t n ;
174
173
void * p ;
175
174
int err = 0 ;
176
175
176
+ if (!iov_iter_count (iter ))
177
+ return 0 ;
178
+
177
179
mutex_lock (& m -> lock );
178
180
179
181
/*
@@ -206,36 +208,34 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
206
208
if (!m -> buf )
207
209
goto Enomem ;
208
210
}
209
- /* if not empty - flush it first */
211
+ // something left in the buffer - copy it out first
210
212
if (m -> count ) {
211
- n = min (m -> count , size );
212
- if (copy_to_iter (m -> buf + m -> from , n , iter ) != n )
213
- goto Efault ;
213
+ n = copy_to_iter (m -> buf + m -> from , m -> count , iter );
214
214
m -> count -= n ;
215
215
m -> from += n ;
216
- size -= n ;
217
216
copied += n ;
218
- if (! size )
217
+ if (m -> count ) // hadn't managed to copy everything
219
218
goto Done ;
220
219
}
221
- /* we need at least one record in buffer */
220
+ // get a non-empty record in the buffer
222
221
m -> from = 0 ;
223
222
p = m -> op -> start (m , & m -> index );
224
223
while (1 ) {
225
224
err = PTR_ERR (p );
226
- if (!p || IS_ERR (p ))
225
+ if (!p || IS_ERR (p )) // EOF or an error
227
226
break ;
228
227
err = m -> op -> show (m , p );
229
- if (err < 0 )
228
+ if (err < 0 ) // hard error
230
229
break ;
231
- if (unlikely (err ))
230
+ if (unlikely (err )) // ->show() says "skip it"
232
231
m -> count = 0 ;
233
- if (unlikely (!m -> count )) {
232
+ if (unlikely (!m -> count )) { // empty record
234
233
p = m -> op -> next (m , p , & m -> index );
235
234
continue ;
236
235
}
237
- if (m -> count < m -> size )
236
+ if (! seq_has_overflowed ( m )) // got it
238
237
goto Fill ;
238
+ // need a bigger buffer
239
239
m -> op -> stop (m , p );
240
240
kvfree (m -> buf );
241
241
m -> count = 0 ;
@@ -244,11 +244,14 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
244
244
goto Enomem ;
245
245
p = m -> op -> start (m , & m -> index );
246
246
}
247
+ // EOF or an error
247
248
m -> op -> stop (m , p );
248
249
m -> count = 0 ;
249
250
goto Done ;
250
251
Fill :
251
- /* they want more? let's try to get some more */
252
+ // one non-empty record is in the buffer; if they want more,
253
+ // try to fit more in, but in any case we need to advance
254
+ // the iterator once for every record shown.
252
255
while (1 ) {
253
256
size_t offs = m -> count ;
254
257
loff_t pos = m -> index ;
@@ -259,30 +262,27 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
259
262
m -> op -> next );
260
263
m -> index ++ ;
261
264
}
262
- if (!p || IS_ERR (p )) {
263
- err = PTR_ERR (p );
265
+ if (!p || IS_ERR (p )) // no next record for us
264
266
break ;
265
- }
266
- if (m -> count >= size )
267
+ if (m -> count >= iov_iter_count (iter ))
267
268
break ;
268
269
err = m -> op -> show (m , p );
269
- if (seq_has_overflowed ( m ) || err ) {
270
+ if (err > 0 ) { // ->show() says "skip it"
270
271
m -> count = offs ;
271
- if (likely (err <= 0 ))
272
- break ;
272
+ } else if (err || seq_has_overflowed (m )) {
273
+ m -> count = offs ;
274
+ break ;
273
275
}
274
276
}
275
277
m -> op -> stop (m , p );
276
- n = min (m -> count , size );
277
- if (copy_to_iter (m -> buf , n , iter ) != n )
278
- goto Efault ;
278
+ n = copy_to_iter (m -> buf , m -> count , iter );
279
279
copied += n ;
280
280
m -> count -= n ;
281
281
m -> from = n ;
282
282
Done :
283
- if (!copied )
284
- copied = err ;
285
- else {
283
+ if (unlikely ( !copied )) {
284
+ copied = m -> count ? - EFAULT : err ;
285
+ } else {
286
286
iocb -> ki_pos += copied ;
287
287
m -> read_pos += copied ;
288
288
}
@@ -291,9 +291,6 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
291
291
Enomem :
292
292
err = - ENOMEM ;
293
293
goto Done ;
294
- Efault :
295
- err = - EFAULT ;
296
- goto Done ;
297
294
}
298
295
EXPORT_SYMBOL (seq_read_iter );
299
296
0 commit comments