Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 131485
b: refs/heads/master
c: 8f19d47
h: refs/heads/master
i:
  131483: a9544ea
v: v3
  • Loading branch information
Eric Biederman authored and Linus Torvalds committed Feb 18, 2009
1 parent 8a4804c commit 5ca25cd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 55ec82176eca52e4e0530a82a0eb59160a1a95a1
refs/heads/master: 8f19d472935c83d823fa4cf02bcc0a7b9952db30
36 changes: 32 additions & 4 deletions trunk/fs/seq_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ int seq_open(struct file *file, const struct seq_operations *op)
*/
file->f_version = 0;

/* SEQ files support lseek, but not pread/pwrite */
file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
/*
* seq_files support lseek() and pread(). They do not implement
* write() at all, but we clear FMODE_PWRITE here for historical
* reasons.
*
* If a client of seq_files a) implements file.write() and b) wishes to
* support pwrite() then that client will need to implement its own
* file.open() which calls seq_open() and then sets FMODE_PWRITE.
*/
file->f_mode &= ~FMODE_PWRITE;
return 0;
}
EXPORT_SYMBOL(seq_open);
Expand Down Expand Up @@ -131,6 +139,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
Expand Down Expand Up @@ -230,8 +254,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
Done:
if (!copied)
copied = err;
else
else {
*ppos += copied;
m->read_pos += copied;
}
file->f_version = m->version;
mutex_unlock(&m->lock);
return copied;
Expand Down Expand Up @@ -266,16 +292,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;
}
}
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/seq_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 5ca25cd

Please sign in to comment.