Skip to content

Commit 7d8761b

Browse files
committed
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull seq_file fix from Al Viro: "This fixes a regression introduced in this cycle wrt iov_iter based variant for reading a seq_file" * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix return values of seq_read_iter()
2 parents cd796ed + 4bbf439 commit 7d8761b

File tree

1 file changed

+27
-30
lines changed

1 file changed

+27
-30
lines changed

fs/seq_file.c

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,14 @@ EXPORT_SYMBOL(seq_read);
168168
ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
169169
{
170170
struct seq_file *m = iocb->ki_filp->private_data;
171-
size_t size = iov_iter_count(iter);
172171
size_t copied = 0;
173172
size_t n;
174173
void *p;
175174
int err = 0;
176175

176+
if (!iov_iter_count(iter))
177+
return 0;
178+
177179
mutex_lock(&m->lock);
178180

179181
/*
@@ -206,36 +208,34 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
206208
if (!m->buf)
207209
goto Enomem;
208210
}
209-
/* if not empty - flush it first */
211+
// something left in the buffer - copy it out first
210212
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);
214214
m->count -= n;
215215
m->from += n;
216-
size -= n;
217216
copied += n;
218-
if (!size)
217+
if (m->count) // hadn't managed to copy everything
219218
goto Done;
220219
}
221-
/* we need at least one record in buffer */
220+
// get a non-empty record in the buffer
222221
m->from = 0;
223222
p = m->op->start(m, &m->index);
224223
while (1) {
225224
err = PTR_ERR(p);
226-
if (!p || IS_ERR(p))
225+
if (!p || IS_ERR(p)) // EOF or an error
227226
break;
228227
err = m->op->show(m, p);
229-
if (err < 0)
228+
if (err < 0) // hard error
230229
break;
231-
if (unlikely(err))
230+
if (unlikely(err)) // ->show() says "skip it"
232231
m->count = 0;
233-
if (unlikely(!m->count)) {
232+
if (unlikely(!m->count)) { // empty record
234233
p = m->op->next(m, p, &m->index);
235234
continue;
236235
}
237-
if (m->count < m->size)
236+
if (!seq_has_overflowed(m)) // got it
238237
goto Fill;
238+
// need a bigger buffer
239239
m->op->stop(m, p);
240240
kvfree(m->buf);
241241
m->count = 0;
@@ -244,11 +244,14 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
244244
goto Enomem;
245245
p = m->op->start(m, &m->index);
246246
}
247+
// EOF or an error
247248
m->op->stop(m, p);
248249
m->count = 0;
249250
goto Done;
250251
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.
252255
while (1) {
253256
size_t offs = m->count;
254257
loff_t pos = m->index;
@@ -259,30 +262,27 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
259262
m->op->next);
260263
m->index++;
261264
}
262-
if (!p || IS_ERR(p)) {
263-
err = PTR_ERR(p);
265+
if (!p || IS_ERR(p)) // no next record for us
264266
break;
265-
}
266-
if (m->count >= size)
267+
if (m->count >= iov_iter_count(iter))
267268
break;
268269
err = m->op->show(m, p);
269-
if (seq_has_overflowed(m) || err) {
270+
if (err > 0) { // ->show() says "skip it"
270271
m->count = offs;
271-
if (likely(err <= 0))
272-
break;
272+
} else if (err || seq_has_overflowed(m)) {
273+
m->count = offs;
274+
break;
273275
}
274276
}
275277
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);
279279
copied += n;
280280
m->count -= n;
281281
m->from = n;
282282
Done:
283-
if (!copied)
284-
copied = err;
285-
else {
283+
if (unlikely(!copied)) {
284+
copied = m->count ? -EFAULT : err;
285+
} else {
286286
iocb->ki_pos += copied;
287287
m->read_pos += copied;
288288
}
@@ -291,9 +291,6 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
291291
Enomem:
292292
err = -ENOMEM;
293293
goto Done;
294-
Efault:
295-
err = -EFAULT;
296-
goto Done;
297294
}
298295
EXPORT_SYMBOL(seq_read_iter);
299296

0 commit comments

Comments
 (0)