aboutsummaryrefslogtreecommitdiffstats
path: root/fs/seq_file.c
diff options
context:
space:
mode:
authorEric Biederman <ebiederm@xmission.com>2009-02-04 18:12:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-02-05 15:56:49 -0500
commit33da8892a2f9e7d4b2d9a35fc80833ba2d2b1aa6 (patch)
tree4261b553653438775461fd408669f1942a383d2e /fs/seq_file.c
parent361916a943cd9dbda1c0b00879d0225cc919d868 (diff)
seq_file: move traverse so it can be used from seq_read
In 2.6.25 some /proc files were converted to use the seq_file infrastructure. But seq_files do not correctly support pread(), which broke some usersapce applications. To handle pread correctly we can't assume that f_pos is where we left it in seq_read. So move traverse() so that we can eventually use it in seq_read and do thus some day support pread(). Signed-off-by: Eric Biederman <ebiederm@xmission.com> Cc: Paul Turner <pjt@google.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/seq_file.c')
-rw-r--r--fs/seq_file.c114
1 files changed, 57 insertions, 57 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c
index b569ff1c4dc8..2716c12eacf5 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -54,6 +54,63 @@ int seq_open(struct file *file, const struct seq_operations *op)
54} 54}
55EXPORT_SYMBOL(seq_open); 55EXPORT_SYMBOL(seq_open);
56 56
57static int traverse(struct seq_file *m, loff_t offset)
58{
59 loff_t pos = 0, index;
60 int error = 0;
61 void *p;
62
63 m->version = 0;
64 index = 0;
65 m->count = m->from = 0;
66 if (!offset) {
67 m->index = index;
68 return 0;
69 }
70 if (!m->buf) {
71 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
72 if (!m->buf)
73 return -ENOMEM;
74 }
75 p = m->op->start(m, &index);
76 while (p) {
77 error = PTR_ERR(p);
78 if (IS_ERR(p))
79 break;
80 error = m->op->show(m, p);
81 if (error < 0)
82 break;
83 if (unlikely(error)) {
84 error = 0;
85 m->count = 0;
86 }
87 if (m->count == m->size)
88 goto Eoverflow;
89 if (pos + m->count > offset) {
90 m->from = offset - pos;
91 m->count -= m->from;
92 m->index = index;
93 break;
94 }
95 pos += m->count;
96 m->count = 0;
97 if (pos == offset) {
98 index++;
99 m->index = index;
100 break;
101 }
102 p = m->op->next(m, p, &index);
103 }
104 m->op->stop(m, p);
105 return error;
106
107Eoverflow:
108 m->op->stop(m, p);
109 kfree(m->buf);
110 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
111 return !m->buf ? -ENOMEM : -EAGAIN;
112}
113
57/** 114/**
58 * seq_read - ->read() method for sequential files. 115 * seq_read - ->read() method for sequential files.
59 * @file: the file to read from 116 * @file: the file to read from
@@ -186,63 +243,6 @@ Efault:
186} 243}
187EXPORT_SYMBOL(seq_read); 244EXPORT_SYMBOL(seq_read);
188 245
189static int traverse(struct seq_file *m, loff_t offset)
190{
191 loff_t pos = 0, index;
192 int error = 0;
193 void *p;
194
195 m->version = 0;
196 index = 0;
197 m->count = m->from = 0;
198 if (!offset) {
199 m->index = index;
200 return 0;
201 }
202 if (!m->buf) {
203 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
204 if (!m->buf)
205 return -ENOMEM;
206 }
207 p = m->op->start(m, &index);
208 while (p) {
209 error = PTR_ERR(p);
210 if (IS_ERR(p))
211 break;
212 error = m->op->show(m, p);
213 if (error < 0)
214 break;
215 if (unlikely(error)) {
216 error = 0;
217 m->count = 0;
218 }
219 if (m->count == m->size)
220 goto Eoverflow;
221 if (pos + m->count > offset) {
222 m->from = offset - pos;
223 m->count -= m->from;
224 m->index = index;
225 break;
226 }
227 pos += m->count;
228 m->count = 0;
229 if (pos == offset) {
230 index++;
231 m->index = index;
232 break;
233 }
234 p = m->op->next(m, p, &index);
235 }
236 m->op->stop(m, p);
237 return error;
238
239Eoverflow:
240 m->op->stop(m, p);
241 kfree(m->buf);
242 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
243 return !m->buf ? -ENOMEM : -EAGAIN;
244}
245
246/** 246/**
247 * seq_lseek - ->llseek() method for sequential files. 247 * seq_lseek - ->llseek() method for sequential files.
248 * @file: the file in question 248 * @file: the file in question