public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Paul Turner <pjt@google.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] seq_file:  Properly cope with pread
Date: Tue, 27 Jan 2009 13:49:45 -0800	[thread overview]
Message-ID: <m1iqo0berq.fsf_-_@fess.ebiederm.org> (raw)
In-Reply-To: <m1mydcbet3.fsf_-_@fess.ebiederm.org> (Eric W. Biederman's message of "Tue\, 27 Jan 2009 13\:48\:56 -0800")


Currently seq_read assumes that the offset passed
to it is always the offset it passed to user space.
In the case pread this assumption is broken and we
do the wrong thing when presented with pread.

To solve this I introduce an offset cache inside of
struct seq_file so we know where our logical file position
is.  Then in seq_read if we try to read from another
offset we reset our data structures and attempt
to go to the offset user space wanted.

Signed-off-by: Eric Biederman <ebiederm@xmission.com>
---
 fs/seq_file.c            |   24 ++++++++++++++++++++++--
 include/linux/seq_file.h |    1 +
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/fs/seq_file.c b/fs/seq_file.c
index 2716c12..cd63d69 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -130,6 +130,22 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 	int err = 0;
 
 	mutex_lock(&m->lock);
+
+	/* 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) {
+			/* With prejudice... */
+			m->read_pos = 0;
+			m->version = 0;
+			m->index = 0;
+			m->count = 0;
+			goto Done;
+		}
+	}
+
 	/*
 	 * 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
@@ -229,8 +245,10 @@ Fill:
 Done:
 	if (!copied)
 		copied = err;
-	else
+	else {
 		*ppos += copied;
+		m->read_pos += copied;
+	}
 	file->f_version = m->version;
 	mutex_unlock(&m->lock);
 	return copied;
@@ -265,16 +283,18 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
 			if (offset < 0)
 				break;
 			retval = offset;
-			if (offset != file->f_pos) {
+			if (offset != m->read_pos) {
 				while ((retval=traverse(m, offset)) == -EAGAIN)
 					;
 				if (retval) {
 					/* with extreme prejudice... */
 					file->f_pos = 0;
+					m->read_pos = 0;
 					m->version = 0;
 					m->index = 0;
 					m->count = 0;
 				} else {
+					m->read_pos = offset;
 					retval = file->f_pos = offset;
 				}
 			}
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 40ea505..f616f31 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -19,6 +19,7 @@ struct seq_file {
 	size_t from;
 	size_t count;
 	loff_t index;
+	loff_t read_pos;
 	u64 version;
 	struct mutex lock;
 	const struct seq_operations *op;
-- 
1.5.6.3


  reply	other threads:[~2009-01-27 21:49 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-17  7:51 Migration of kernel interfaces to seq_files breaks pread() consumers Paul Turner
2009-01-25  2:19 ` Andrew Morton
2009-01-25  3:40   ` Paul Turner
2009-01-25 12:08   ` Alexey Dobriyan
2009-01-27 21:47     ` Eric W. Biederman
2009-01-27 21:48       ` [PATCH 1/2] seq_file: Move traverse so it can be used from seq_read Eric W. Biederman
2009-01-27 21:49         ` Eric W. Biederman [this message]
2009-01-30  1:26       ` Migration of kernel interfaces to seq_files breaks pread() consumers Paul Turner
2009-01-30  3:01         ` Eric W. Biederman
2009-01-30  6:09           ` Paul Turner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m1iqo0berq.fsf_-_@fess.ebiederm.org \
    --to=ebiederm@xmission.com \
    --cc=adobriyan@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pjt@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox