Merge tag 'zonefs-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal...
[linux-2.6-microblaze.git] / fs / seq_file.c
index 3b20e21..cb11a34 100644 (file)
@@ -168,12 +168,14 @@ 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;
        int err = 0;
 
+       if (!iov_iter_count(iter))
+               return 0;
+
        mutex_lock(&m->lock);
 
        /*
@@ -206,36 +208,34 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                if (!m->buf)
                        goto Enomem;
        }
-       /* if not empty - flush it first */
+       // something left in the buffer - copy it out 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)
+               if (m->count)   // hadn't managed to copy everything
                        goto Done;
        }
-       /* we need at least one record in buffer */
+       // get a non-empty record in the buffer
        m->from = 0;
        p = m->op->start(m, &m->index);
        while (1) {
                err = PTR_ERR(p);
-               if (!p || IS_ERR(p))
+               if (!p || IS_ERR(p))    // EOF or an error
                        break;
                err = m->op->show(m, p);
-               if (err < 0)
+               if (err < 0)            // hard error
                        break;
-               if (unlikely(err))
+               if (unlikely(err))      // ->show() says "skip it"
                        m->count = 0;
-               if (unlikely(!m->count)) {
+               if (unlikely(!m->count)) { // empty record
                        p = m->op->next(m, p, &m->index);
                        continue;
                }
-               if (m->count < m->size)
+               if (!seq_has_overflowed(m)) // got it
                        goto Fill;
+               // need a bigger buffer
                m->op->stop(m, p);
                kvfree(m->buf);
                m->count = 0;
@@ -244,11 +244,14 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                        goto Enomem;
                p = m->op->start(m, &m->index);
        }
+       // EOF or an error
        m->op->stop(m, p);
        m->count = 0;
        goto Done;
 Fill:
-       /* they want more? let's try to get some more */
+       // one non-empty record is in the buffer; if they want more,
+       // try to fit more in, but in any case we need to advance
+       // the iterator once for every record shown.
        while (1) {
                size_t offs = m->count;
                loff_t pos = m->index;
@@ -259,30 +262,27 @@ Fill:
                                            m->op->next);
                        m->index++;
                }
-               if (!p || IS_ERR(p)) {
-                       err = PTR_ERR(p);
+               if (!p || IS_ERR(p))    // no next record for us
                        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) {
+               if (err > 0) {          // ->show() says "skip it"
                        m->count = offs;
-                       if (likely(err <= 0))
-                               break;
+               } else if (err || seq_has_overflowed(m)) {
+                       m->count = offs;
+                       break;
                }
        }
        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;
 Done:
-       if (!copied)
-               copied = err;
-       else {
+       if (unlikely(!copied)) {
+               copied = m->count ? -EFAULT : err;
+       else {
                iocb->ki_pos += copied;
                m->read_pos += copied;
        }
@@ -291,9 +291,6 @@ Done:
 Enomem:
        err = -ENOMEM;
        goto Done;
-Efault:
-       err = -EFAULT;
-       goto Done;
 }
 EXPORT_SYMBOL(seq_read_iter);
 
@@ -672,7 +669,8 @@ void seq_puts(struct seq_file *m, const char *s)
 EXPORT_SYMBOL(seq_puts);
 
 /**
- * A helper routine for putting decimal numbers without rich format of printf().
+ * seq_put_decimal_ull_width - A helper routine for putting decimal numbers
+ *                            without rich format of printf().
  * only 'unsigned long long' is supported.
  * @m: seq_file identifying the buffer to which data should be written
  * @delimiter: a string which is printed before the number
@@ -1047,7 +1045,7 @@ struct hlist_node *seq_hlist_next_rcu(void *v,
 EXPORT_SYMBOL(seq_hlist_next_rcu);
 
 /**
- * seq_hlist_start_precpu - start an iteration of a percpu hlist array
+ * seq_hlist_start_percpu - start an iteration of a percpu hlist array
  * @head: pointer to percpu array of struct hlist_heads
  * @cpu:  pointer to cpu "cursor"
  * @pos:  start position of sequence