hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/fs/seq_file.c
....@@ -6,6 +6,8 @@
66 * initial implementation -- AV, Oct 2001.
77 */
88
9
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
+
911 #include <linux/cache.h>
1012 #include <linux/fs.h>
1113 #include <linux/export.h>
....@@ -16,6 +18,7 @@
1618 #include <linux/mm.h>
1719 #include <linux/printk.h>
1820 #include <linux/string_helpers.h>
21
+#include <linux/uio.h>
1922
2023 #include <linux/uaccess.h>
2124 #include <asm/page.h>
....@@ -71,13 +74,6 @@
7174 p->file = file;
7275
7376 /*
74
- * Wrappers around seq_open(e.g. swaps_open) need to be
75
- * aware of this. If they set f_version themselves, they
76
- * should call seq_open first and then set f_version.
77
- */
78
- file->f_version = 0;
79
-
80
- /*
8177 * seq_files support lseek() and pread(). They do not implement
8278 * write() at all, but we clear FMODE_PWRITE here for historical
8379 * reasons.
....@@ -97,7 +93,6 @@
9793 int error = 0;
9894 void *p;
9995
100
- m->version = 0;
10196 m->index = 0;
10297 m->count = m->from = 0;
10398 if (!offset)
....@@ -155,50 +150,58 @@
155150 */
156151 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
157152 {
158
- struct seq_file *m = file->private_data;
153
+ struct iovec iov = { .iov_base = buf, .iov_len = size};
154
+ struct kiocb kiocb;
155
+ struct iov_iter iter;
156
+ ssize_t ret;
157
+
158
+ init_sync_kiocb(&kiocb, file);
159
+ iov_iter_init(&iter, READ, &iov, 1, size);
160
+
161
+ kiocb.ki_pos = *ppos;
162
+ ret = seq_read_iter(&kiocb, &iter);
163
+ *ppos = kiocb.ki_pos;
164
+ return ret;
165
+}
166
+EXPORT_SYMBOL(seq_read);
167
+
168
+/*
169
+ * Ready-made ->f_op->read_iter()
170
+ */
171
+ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
172
+{
173
+ struct seq_file *m = iocb->ki_filp->private_data;
159174 size_t copied = 0;
160175 size_t n;
161176 void *p;
162177 int err = 0;
163178
164
- mutex_lock(&m->lock);
179
+ if (!iov_iter_count(iter))
180
+ return 0;
165181
166
- /*
167
- * seq_file->op->..m_start/m_stop/m_next may do special actions
168
- * or optimisations based on the file->f_version, so we want to
169
- * pass the file->f_version to those methods.
170
- *
171
- * seq_file->version is just copy of f_version, and seq_file
172
- * methods can treat it simply as file version.
173
- * It is copied in first and copied out after all operations.
174
- * It is convenient to have it as part of structure to avoid the
175
- * need of passing another argument to all the seq_file methods.
176
- */
177
- m->version = file->f_version;
182
+ mutex_lock(&m->lock);
178183
179184 /*
180185 * if request is to read from zero offset, reset iterator to first
181186 * record as it might have been already advanced by previous requests
182187 */
183
- if (*ppos == 0) {
188
+ if (iocb->ki_pos == 0) {
184189 m->index = 0;
185
- m->version = 0;
186190 m->count = 0;
187191 }
188192
189
- /* Don't assume *ppos is where we left it */
190
- if (unlikely(*ppos != m->read_pos)) {
191
- while ((err = traverse(m, *ppos)) == -EAGAIN)
193
+ /* Don't assume ki_pos is where we left it */
194
+ if (unlikely(iocb->ki_pos != m->read_pos)) {
195
+ while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
192196 ;
193197 if (err) {
194198 /* With prejudice... */
195199 m->read_pos = 0;
196
- m->version = 0;
197200 m->index = 0;
198201 m->count = 0;
199202 goto Done;
200203 } else {
201
- m->read_pos = *ppos;
204
+ m->read_pos = iocb->ki_pos;
202205 }
203206 }
204207
....@@ -208,99 +211,91 @@
208211 if (!m->buf)
209212 goto Enomem;
210213 }
211
- /* if not empty - flush it first */
214
+ // something left in the buffer - copy it out first
212215 if (m->count) {
213
- n = min(m->count, size);
214
- err = copy_to_user(buf, m->buf + m->from, n);
215
- if (err)
216
- goto Efault;
216
+ n = copy_to_iter(m->buf + m->from, m->count, iter);
217217 m->count -= n;
218218 m->from += n;
219
- size -= n;
220
- buf += n;
221219 copied += n;
222
- if (!size)
220
+ if (m->count) // hadn't managed to copy everything
223221 goto Done;
224222 }
225
- /* we need at least one record in buffer */
223
+ // get a non-empty record in the buffer
226224 m->from = 0;
227225 p = m->op->start(m, &m->index);
228226 while (1) {
229227 err = PTR_ERR(p);
230
- if (!p || IS_ERR(p))
228
+ if (!p || IS_ERR(p)) // EOF or an error
231229 break;
232230 err = m->op->show(m, p);
233
- if (err < 0)
231
+ if (err < 0) // hard error
234232 break;
235
- if (unlikely(err))
233
+ if (unlikely(err)) // ->show() says "skip it"
236234 m->count = 0;
237
- if (unlikely(!m->count)) {
235
+ if (unlikely(!m->count)) { // empty record
238236 p = m->op->next(m, p, &m->index);
239237 continue;
240238 }
241
- if (m->count < m->size)
239
+ if (!seq_has_overflowed(m)) // got it
242240 goto Fill;
241
+ // need a bigger buffer
243242 m->op->stop(m, p);
244243 kvfree(m->buf);
245244 m->count = 0;
246245 m->buf = seq_buf_alloc(m->size <<= 1);
247246 if (!m->buf)
248247 goto Enomem;
249
- m->version = 0;
250248 p = m->op->start(m, &m->index);
251249 }
250
+ // EOF or an error
252251 m->op->stop(m, p);
253252 m->count = 0;
254253 goto Done;
255254 Fill:
256
- /* they want more? let's try to get some more */
255
+ // one non-empty record is in the buffer; if they want more,
256
+ // try to fit more in, but in any case we need to advance
257
+ // the iterator once for every record shown.
257258 while (1) {
258259 size_t offs = m->count;
259260 loff_t pos = m->index;
260261
261262 p = m->op->next(m, p, &m->index);
262
- if (pos == m->index)
263
- /* Buggy ->next function */
263
+ if (pos == m->index) {
264
+ pr_info_ratelimited("buggy .next function %ps did not update position index\n",
265
+ m->op->next);
264266 m->index++;
265
- if (!p || IS_ERR(p)) {
266
- err = PTR_ERR(p);
267
- break;
268267 }
269
- if (m->count >= size)
268
+ if (!p || IS_ERR(p)) // no next record for us
269
+ break;
270
+ if (m->count >= iov_iter_count(iter))
270271 break;
271272 err = m->op->show(m, p);
272
- if (seq_has_overflowed(m) || err) {
273
+ if (err > 0) { // ->show() says "skip it"
273274 m->count = offs;
274
- if (likely(err <= 0))
275
- break;
275
+ } else if (err || seq_has_overflowed(m)) {
276
+ m->count = offs;
277
+ break;
276278 }
277279 }
278280 m->op->stop(m, p);
279
- n = min(m->count, size);
280
- err = copy_to_user(buf, m->buf, n);
281
- if (err)
282
- goto Efault;
281
+ n = copy_to_iter(m->buf, m->count, iter);
283282 copied += n;
284283 m->count -= n;
285284 m->from = n;
286285 Done:
287
- if (!copied)
288
- copied = err;
289
- else {
290
- *ppos += copied;
286
+ if (unlikely(!copied)) {
287
+ copied = m->count ? -EFAULT : err;
288
+ } else {
289
+ iocb->ki_pos += copied;
291290 m->read_pos += copied;
292291 }
293
- file->f_version = m->version;
294292 mutex_unlock(&m->lock);
295293 return copied;
296294 Enomem:
297295 err = -ENOMEM;
298296 goto Done;
299
-Efault:
300
- err = -EFAULT;
301
- goto Done;
302297 }
303
-EXPORT_SYMBOL(seq_read);
298
+EXPORT_SYMBOL(seq_read_iter);
304299
305300 /**
306301 * seq_lseek - ->llseek() method for sequential files.
....@@ -316,10 +311,10 @@
316311 loff_t retval = -EINVAL;
317312
318313 mutex_lock(&m->lock);
319
- m->version = file->f_version;
320314 switch (whence) {
321315 case SEEK_CUR:
322316 offset += file->f_pos;
317
+ fallthrough;
323318 case SEEK_SET:
324319 if (offset < 0)
325320 break;
....@@ -331,7 +326,6 @@
331326 /* with extreme prejudice... */
332327 file->f_pos = 0;
333328 m->read_pos = 0;
334
- m->version = 0;
335329 m->index = 0;
336330 m->count = 0;
337331 } else {
....@@ -342,7 +336,6 @@
342336 file->f_pos = offset;
343337 }
344338 }
345
- file->f_version = m->version;
346339 mutex_unlock(&m->lock);
347340 return retval;
348341 }
....@@ -386,6 +379,17 @@
386379 }
387380 EXPORT_SYMBOL(seq_escape);
388381
382
+void seq_escape_mem_ascii(struct seq_file *m, const char *src, size_t isz)
383
+{
384
+ char *buf;
385
+ size_t size = seq_get_buf(m, &buf);
386
+ int ret;
387
+
388
+ ret = string_escape_mem_ascii(src, isz, buf, size);
389
+ seq_commit(m, ret < size ? ret : -1);
390
+}
391
+EXPORT_SYMBOL(seq_escape_mem_ascii);
392
+
389393 void seq_vprintf(struct seq_file *m, const char *f, va_list args)
390394 {
391395 int len;