On Sat, Nov 14, 2020 at 08:50:00PM +0000, Al Viro wrote: OK, I think I understand what's going on. Could you check if reverting the variant in -next and applying the following instead fixes what you are seeing? diff --git a/fs/seq_file.c b/fs/seq_file.c index 3b20e21604e7..35667112bbd1 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -168,7 +168,6 @@ EXPORT_SYMBOL(seq_read); ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) { struct seq_file *m = iocb->ki_filp->private_data; - size_t size = iov_iter_count(iter); size_t copied = 0; size_t n; void *p; @@ -208,16 +207,15 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) } /* if not empty - flush it first */ if (m->count) { - n = min(m->count, size); - if (copy_to_iter(m->buf + m->from, n, iter) != n) - goto Efault; + n = copy_to_iter(m->buf + m->from, m->count, iter); m->count -= n; m->from += n; - size -= n; copied += n; - if (!size) - goto Done; + if (m->count) + goto Efault; } + if (!iov_iter_count(iter)) + goto Done; /* we need at least one record in buffer */ m->from = 0; p = m->op->start(m, &m->index); @@ -249,6 +247,7 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) goto Done; Fill: /* they want more? let's try to get some more */ + /* m->count is positive and there's space left in iter */ while (1) { size_t offs = m->count; loff_t pos = m->index; @@ -263,7 +262,7 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) err = PTR_ERR(p); break; } - if (m->count >= size) + if (m->count >= iov_iter_count(iter)) break; err = m->op->show(m, p); if (seq_has_overflowed(m) || err) { @@ -273,12 +272,12 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) } } m->op->stop(m, p); - n = min(m->count, size); - if (copy_to_iter(m->buf, n, iter) != n) - goto Efault; + n = copy_to_iter(m->buf, m->count, iter); copied += n; - m->count -= n; m->from = n; + m->count -= n; + if (m->count) + goto Efault; Done: if (!copied) copied = err;