|
@@ -140,9 +140,21 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
|
|
|
|
|
|
mutex_lock(&m->lock);
|
|
|
|
|
|
+ /*
|
|
|
+ * seq_file->op->..m_start/m_stop/m_next may do special actions
|
|
|
+ * or optimisations based on the file->f_version, so we want to
|
|
|
+ * pass the file->f_version to those methods.
|
|
|
+ *
|
|
|
+ * seq_file->version is just copy of f_version, and seq_file
|
|
|
+ * methods can treat it simply as file version.
|
|
|
+ * It is copied in first and copied out after all operations.
|
|
|
+ * It is convenient to have it as part of structure to avoid the
|
|
|
+ * need of passing another argument to all the seq_file methods.
|
|
|
+ */
|
|
|
+ m->version = file->f_version;
|
|
|
+
|
|
|
/* Don't assume *ppos is where we left it */
|
|
|
if (unlikely(*ppos != m->read_pos)) {
|
|
|
- m->read_pos = *ppos;
|
|
|
while ((err = traverse(m, *ppos)) == -EAGAIN)
|
|
|
;
|
|
|
if (err) {
|
|
@@ -152,21 +164,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
|
|
|
m->index = 0;
|
|
|
m->count = 0;
|
|
|
goto Done;
|
|
|
+ } else {
|
|
|
+ m->read_pos = *ppos;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * seq_file->op->..m_start/m_stop/m_next may do special actions
|
|
|
- * or optimisations based on the file->f_version, so we want to
|
|
|
- * pass the file->f_version to those methods.
|
|
|
- *
|
|
|
- * seq_file->version is just copy of f_version, and seq_file
|
|
|
- * methods can treat it simply as file version.
|
|
|
- * It is copied in first and copied out after all operations.
|
|
|
- * It is convenient to have it as part of structure to avoid the
|
|
|
- * need of passing another argument to all the seq_file methods.
|
|
|
- */
|
|
|
- m->version = file->f_version;
|
|
|
/* grab buffer if we didn't have one */
|
|
|
if (!m->buf) {
|
|
|
m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
|