Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/seq_file.c
4 : : *
5 : : * helper functions for making synthetic files from sequences of records.
6 : : * initial implementation -- AV, Oct 2001.
7 : : */
8 : :
9 : : #include <linux/cache.h>
10 : : #include <linux/fs.h>
11 : : #include <linux/export.h>
12 : : #include <linux/seq_file.h>
13 : : #include <linux/vmalloc.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/cred.h>
16 : : #include <linux/mm.h>
17 : : #include <linux/printk.h>
18 : : #include <linux/string_helpers.h>
19 : :
20 : : #include <linux/uaccess.h>
21 : : #include <asm/page.h>
22 : :
23 : : static struct kmem_cache *seq_file_cache __ro_after_init;
24 : :
25 : 4242 : static void seq_set_overflow(struct seq_file *m)
26 : : {
27 : 4242 : m->count = m->size;
28 : 0 : }
29 : :
30 : 41291 : static void *seq_buf_alloc(unsigned long size)
31 : : {
32 : 41291 : return kvmalloc(size, GFP_KERNEL_ACCOUNT);
33 : : }
34 : :
35 : : /**
36 : : * seq_open - initialize sequential file
37 : : * @file: file we initialize
38 : : * @op: method table describing the sequence
39 : : *
40 : : * seq_open() sets @file, associating it with a sequence described
41 : : * by @op. @op->start() sets the iterator up and returns the first
42 : : * element of sequence. @op->stop() shuts it down. @op->next()
43 : : * returns the next element of sequence. @op->show() prints element
44 : : * into the buffer. In case of error ->start() and ->next() return
45 : : * ERR_PTR(error). In the end of sequence they return %NULL. ->show()
46 : : * returns 0 in case of success and negative number in case of error.
47 : : * Returning SEQ_SKIP means "discard this element and move on".
48 : : * Note: seq_open() will allocate a struct seq_file and store its
49 : : * pointer in @file->private_data. This pointer should not be modified.
50 : : */
51 : 53597 : int seq_open(struct file *file, const struct seq_operations *op)
52 : : {
53 : 53597 : struct seq_file *p;
54 : :
55 [ - + ]: 53597 : WARN_ON(file->private_data);
56 : :
57 : 53597 : p = kmem_cache_zalloc(seq_file_cache, GFP_KERNEL);
58 [ + - ]: 53597 : if (!p)
59 : : return -ENOMEM;
60 : :
61 : 53597 : file->private_data = p;
62 : :
63 : 53597 : mutex_init(&p->lock);
64 : 53597 : p->op = op;
65 : :
66 : : // No refcounting: the lifetime of 'p' is constrained
67 : : // to the lifetime of the file.
68 : 53597 : p->file = file;
69 : :
70 : : /*
71 : : * Wrappers around seq_open(e.g. swaps_open) need to be
72 : : * aware of this. If they set f_version themselves, they
73 : : * should call seq_open first and then set f_version.
74 : : */
75 : 53597 : file->f_version = 0;
76 : :
77 : : /*
78 : : * seq_files support lseek() and pread(). They do not implement
79 : : * write() at all, but we clear FMODE_PWRITE here for historical
80 : : * reasons.
81 : : *
82 : : * If a client of seq_files a) implements file.write() and b) wishes to
83 : : * support pwrite() then that client will need to implement its own
84 : : * file.open() which calls seq_open() and then sets FMODE_PWRITE.
85 : : */
86 : 53597 : file->f_mode &= ~FMODE_PWRITE;
87 : 53597 : return 0;
88 : : }
89 : : EXPORT_SYMBOL(seq_open);
90 : :
91 : 882 : static int traverse(struct seq_file *m, loff_t offset)
92 : : {
93 : 882 : loff_t pos = 0;
94 : 882 : int error = 0;
95 : 882 : void *p;
96 : :
97 : 882 : m->version = 0;
98 : 882 : m->index = 0;
99 : 882 : m->count = m->from = 0;
100 [ - + ]: 882 : if (!offset)
101 : : return 0;
102 : :
103 [ # # ]: 0 : if (!m->buf) {
104 : 0 : m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
105 [ # # ]: 0 : if (!m->buf)
106 : : return -ENOMEM;
107 : : }
108 : 0 : p = m->op->start(m, &m->index);
109 [ # # ]: 0 : while (p) {
110 [ # # ]: 0 : error = PTR_ERR(p);
111 [ # # ]: 0 : if (IS_ERR(p))
112 : : break;
113 : 0 : error = m->op->show(m, p);
114 [ # # ]: 0 : if (error < 0)
115 : : break;
116 [ # # ]: 0 : if (unlikely(error)) {
117 : 0 : error = 0;
118 : 0 : m->count = 0;
119 : : }
120 [ # # ]: 0 : if (seq_has_overflowed(m))
121 : 0 : goto Eoverflow;
122 : 0 : p = m->op->next(m, p, &m->index);
123 [ # # ]: 0 : if (pos + m->count > offset) {
124 : 0 : m->from = offset - pos;
125 : 0 : m->count -= m->from;
126 : 0 : break;
127 : : }
128 : 0 : pos += m->count;
129 : 0 : m->count = 0;
130 [ # # ]: 0 : if (pos == offset)
131 : : break;
132 : : }
133 : 0 : m->op->stop(m, p);
134 : 0 : return error;
135 : :
136 : : Eoverflow:
137 : 0 : m->op->stop(m, p);
138 : 0 : kvfree(m->buf);
139 : 0 : m->count = 0;
140 : 0 : m->buf = seq_buf_alloc(m->size <<= 1);
141 [ # # ]: 0 : return !m->buf ? -ENOMEM : -EAGAIN;
142 : : }
143 : :
144 : : /**
145 : : * seq_read - ->read() method for sequential files.
146 : : * @file: the file to read from
147 : : * @buf: the buffer to read to
148 : : * @size: the maximum number of bytes to read
149 : : * @ppos: the current position in the file
150 : : *
151 : : * Ready-made ->f_op->read()
152 : : */
153 : 115801 : ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
154 : : {
155 : 115801 : struct seq_file *m = file->private_data;
156 : 115801 : size_t copied = 0;
157 : 115801 : size_t n;
158 : 115801 : void *p;
159 : 115801 : int err = 0;
160 : :
161 : 115801 : mutex_lock(&m->lock);
162 : :
163 : : /*
164 : : * seq_file->op->..m_start/m_stop/m_next may do special actions
165 : : * or optimisations based on the file->f_version, so we want to
166 : : * pass the file->f_version to those methods.
167 : : *
168 : : * seq_file->version is just copy of f_version, and seq_file
169 : : * methods can treat it simply as file version.
170 : : * It is copied in first and copied out after all operations.
171 : : * It is convenient to have it as part of structure to avoid the
172 : : * need of passing another argument to all the seq_file methods.
173 : : */
174 : 115801 : m->version = file->f_version;
175 : :
176 : : /*
177 : : * if request is to read from zero offset, reset iterator to first
178 : : * record as it might have been already advanced by previous requests
179 : : */
180 [ + + ]: 115801 : if (*ppos == 0) {
181 : 74527 : m->index = 0;
182 : 74527 : m->version = 0;
183 : 74527 : m->count = 0;
184 : : }
185 : :
186 : : /* Don't assume *ppos is where we left it */
187 [ - + ]: 115801 : if (unlikely(*ppos != m->read_pos)) {
188 [ # # ]: 0 : while ((err = traverse(m, *ppos)) == -EAGAIN)
189 : 0 : ;
190 [ # # ]: 0 : if (err) {
191 : : /* With prejudice... */
192 : 0 : m->read_pos = 0;
193 : 0 : m->version = 0;
194 : 0 : m->index = 0;
195 : 0 : m->count = 0;
196 : 0 : goto Done;
197 : : } else {
198 : 0 : m->read_pos = *ppos;
199 : : }
200 : : }
201 : :
202 : : /* grab buffer if we didn't have one */
203 [ + + ]: 115801 : if (!m->buf) {
204 : 39191 : m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
205 [ - + ]: 39191 : if (!m->buf)
206 : 0 : goto Enomem;
207 : : }
208 : : /* if not empty - flush it first */
209 [ + + ]: 115801 : if (m->count) {
210 : 6472 : n = min(m->count, size);
211 [ - + ]: 6472 : err = copy_to_user(buf, m->buf + m->from, n);
212 [ - + ]: 6472 : if (err)
213 : 0 : goto Efault;
214 : 6472 : m->count -= n;
215 : 6472 : m->from += n;
216 : 6472 : size -= n;
217 : 6472 : buf += n;
218 : 6472 : copied += n;
219 [ - + ]: 6472 : if (!size)
220 : 0 : goto Done;
221 : : }
222 : : /* we need at least one record in buffer */
223 : 115801 : m->from = 0;
224 : 115801 : p = m->op->start(m, &m->index);
225 : 125927 : while (1) {
226 [ + + ]: 125927 : err = PTR_ERR(p);
227 [ + + + - ]: 125927 : if (!p || IS_ERR(p))
228 : : break;
229 : 86400 : err = m->op->show(m, p);
230 [ + + ]: 86400 : if (err < 0)
231 : : break;
232 [ + + ]: 51799 : if (unlikely(err))
233 : 1747 : m->count = 0;
234 [ + + ]: 51799 : if (unlikely(!m->count)) {
235 : 8026 : p = m->op->next(m, p, &m->index);
236 : 8026 : continue;
237 : : }
238 [ + + ]: 43773 : if (m->count < m->size)
239 : 41673 : goto Fill;
240 : 2100 : m->op->stop(m, p);
241 : 2100 : kvfree(m->buf);
242 : 2100 : m->count = 0;
243 : 2100 : m->buf = seq_buf_alloc(m->size <<= 1);
244 [ - + ]: 2100 : if (!m->buf)
245 : 0 : goto Enomem;
246 : 2100 : m->version = 0;
247 : 2100 : p = m->op->start(m, &m->index);
248 : : }
249 : 74128 : m->op->stop(m, p);
250 : 74128 : m->count = 0;
251 : 74128 : goto Done;
252 : : Fill:
253 : : /* they want more? let's try to get some more */
254 : 109391 : while (1) {
255 : 109391 : size_t offs = m->count;
256 : 109391 : loff_t pos = m->index;
257 : :
258 : 109391 : p = m->op->next(m, p, &m->index);
259 [ + + ]: 109391 : if (pos == m->index)
260 : : /* Buggy ->next function */
261 : 6174 : m->index++;
262 [ + + - + ]: 109391 : if (!p || IS_ERR(p)) {
263 : 32954 : err = PTR_ERR(p);
264 : 32954 : break;
265 : : }
266 [ + + ]: 76437 : if (m->count >= size)
267 : : break;
268 : 69860 : err = m->op->show(m, p);
269 [ + + + - ]: 69860 : if (seq_has_overflowed(m) || err) {
270 : 2142 : m->count = offs;
271 [ - + ]: 2142 : if (likely(err <= 0))
272 : : break;
273 : : }
274 : : }
275 : 41673 : m->op->stop(m, p);
276 : 41673 : n = min(m->count, size);
277 [ - + ]: 41673 : err = copy_to_user(buf, m->buf, n);
278 [ - + ]: 41673 : if (err)
279 : 0 : goto Efault;
280 : 41673 : copied += n;
281 : 41673 : m->count -= n;
282 : 41673 : m->from = n;
283 : 115801 : Done:
284 [ + + ]: 115801 : if (!copied)
285 : 74107 : copied = err;
286 : : else {
287 : 41694 : *ppos += copied;
288 : 41694 : m->read_pos += copied;
289 : : }
290 : 115801 : file->f_version = m->version;
291 : 115801 : mutex_unlock(&m->lock);
292 : 115801 : return copied;
293 : : Enomem:
294 : 0 : err = -ENOMEM;
295 : 0 : goto Done;
296 : : Efault:
297 : 0 : err = -EFAULT;
298 : 0 : goto Done;
299 : : }
300 : : EXPORT_SYMBOL(seq_read);
301 : :
302 : : /**
303 : : * seq_lseek - ->llseek() method for sequential files.
304 : : * @file: the file in question
305 : : * @offset: new position
306 : : * @whence: 0 for absolute, 1 for relative position
307 : : *
308 : : * Ready-made ->f_op->llseek()
309 : : */
310 : 924 : loff_t seq_lseek(struct file *file, loff_t offset, int whence)
311 : : {
312 : 924 : struct seq_file *m = file->private_data;
313 : 924 : loff_t retval = -EINVAL;
314 : :
315 : 924 : mutex_lock(&m->lock);
316 : 924 : m->version = file->f_version;
317 [ - + - ]: 924 : switch (whence) {
318 : 0 : case SEEK_CUR:
319 : 0 : offset += file->f_pos;
320 : : /* fall through */
321 : 924 : case SEEK_SET:
322 [ + - ]: 924 : if (offset < 0)
323 : : break;
324 : 924 : retval = offset;
325 [ + + ]: 924 : if (offset != m->read_pos) {
326 [ - + ]: 882 : while ((retval = traverse(m, offset)) == -EAGAIN)
327 : 882 : ;
328 [ - + ]: 882 : if (retval) {
329 : : /* with extreme prejudice... */
330 : 0 : file->f_pos = 0;
331 : 0 : m->read_pos = 0;
332 : 0 : m->version = 0;
333 : 0 : m->index = 0;
334 : 0 : m->count = 0;
335 : : } else {
336 : 882 : m->read_pos = offset;
337 : 882 : retval = file->f_pos = offset;
338 : : }
339 : : } else {
340 : 42 : file->f_pos = offset;
341 : : }
342 : : }
343 : 924 : file->f_version = m->version;
344 : 924 : mutex_unlock(&m->lock);
345 : 924 : return retval;
346 : : }
347 : : EXPORT_SYMBOL(seq_lseek);
348 : :
349 : : /**
350 : : * seq_release - free the structures associated with sequential file.
351 : : * @file: file in question
352 : : * @inode: its inode
353 : : *
354 : : * Frees the structures associated with sequential file; can be used
355 : : * as ->f_op->release() if you don't have private data to destroy.
356 : : */
357 : 53555 : int seq_release(struct inode *inode, struct file *file)
358 : : {
359 : 53555 : struct seq_file *m = file->private_data;
360 : 44147 : kvfree(m->buf);
361 : 53555 : kmem_cache_free(seq_file_cache, m);
362 : 53555 : return 0;
363 : : }
364 : : EXPORT_SYMBOL(seq_release);
365 : :
366 : : /**
367 : : * seq_escape - print string into buffer, escaping some characters
368 : : * @m: target buffer
369 : : * @s: string
370 : : * @esc: set of characters that need escaping
371 : : *
372 : : * Puts string into buffer, replacing each occurrence of character from
373 : : * @esc with usual octal escape.
374 : : * Use seq_has_overflowed() to check for errors.
375 : : */
376 : 171079 : void seq_escape(struct seq_file *m, const char *s, const char *esc)
377 : : {
378 : 171079 : char *buf;
379 [ - + ]: 171079 : size_t size = seq_get_buf(m, &buf);
380 : 171079 : int ret;
381 : :
382 : 171079 : ret = string_escape_str(s, buf, size, ESCAPE_OCTAL, esc);
383 [ - + - + ]: 171079 : seq_commit(m, ret < size ? ret : -1);
384 : 171079 : }
385 : : EXPORT_SYMBOL(seq_escape);
386 : :
387 : 0 : void seq_escape_mem_ascii(struct seq_file *m, const char *src, size_t isz)
388 : : {
389 : 0 : char *buf;
390 [ # # ]: 0 : size_t size = seq_get_buf(m, &buf);
391 : 0 : int ret;
392 : :
393 : 0 : ret = string_escape_mem_ascii(src, isz, buf, size);
394 [ # # # # ]: 0 : seq_commit(m, ret < size ? ret : -1);
395 : 0 : }
396 : : EXPORT_SYMBOL(seq_escape_mem_ascii);
397 : :
398 : 216727 : void seq_vprintf(struct seq_file *m, const char *f, va_list args)
399 : : {
400 : 216727 : int len;
401 : :
402 [ + - ]: 216727 : if (m->count < m->size) {
403 : 216727 : len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
404 [ + - ]: 216727 : if (m->count + len < m->size) {
405 : 216727 : m->count += len;
406 : 216727 : return;
407 : : }
408 : : }
409 : 0 : seq_set_overflow(m);
410 : : }
411 : : EXPORT_SYMBOL(seq_vprintf);
412 : :
413 : 216727 : void seq_printf(struct seq_file *m, const char *f, ...)
414 : : {
415 : 216727 : va_list args;
416 : :
417 : 216727 : va_start(args, f);
418 : 216727 : seq_vprintf(m, f, args);
419 : 216727 : va_end(args);
420 : 216727 : }
421 : : EXPORT_SYMBOL(seq_printf);
422 : :
423 : : /**
424 : : * mangle_path - mangle and copy path to buffer beginning
425 : : * @s: buffer start
426 : : * @p: beginning of path in above buffer
427 : : * @esc: set of characters that need escaping
428 : : *
429 : : * Copy the path from @p to @s, replacing each occurrence of character from
430 : : * @esc with usual octal escape.
431 : : * Returns pointer past last written character in @s, or NULL in case of
432 : : * failure.
433 : : */
434 : 134612 : char *mangle_path(char *s, const char *p, const char *esc)
435 : : {
436 [ + - ]: 2546985 : while (s <= p) {
437 : 2546985 : char c = *p++;
438 [ + + ]: 2546985 : if (!c) {
439 : 134612 : return s;
440 [ + - ]: 2412373 : } else if (!strchr(esc, c)) {
441 : 2412373 : *s++ = c;
442 [ # # ]: 0 : } else if (s + 4 > p) {
443 : : break;
444 : : } else {
445 : 0 : *s++ = '\\';
446 : 0 : *s++ = '0' + ((c & 0300) >> 6);
447 : 0 : *s++ = '0' + ((c & 070) >> 3);
448 : 0 : *s++ = '0' + (c & 07);
449 : : }
450 : : }
451 : : return NULL;
452 : : }
453 : : EXPORT_SYMBOL(mangle_path);
454 : :
455 : : /**
456 : : * seq_path - seq_file interface to print a pathname
457 : : * @m: the seq_file handle
458 : : * @path: the struct path to print
459 : : * @esc: set of characters to escape in the output
460 : : *
461 : : * return the absolute path of 'path', as represented by the
462 : : * dentry / mnt pair in the path parameter.
463 : : */
464 : 0 : int seq_path(struct seq_file *m, const struct path *path, const char *esc)
465 : : {
466 : 0 : char *buf;
467 [ # # ]: 0 : size_t size = seq_get_buf(m, &buf);
468 : 0 : int res = -1;
469 : :
470 [ # # ]: 0 : if (size) {
471 : 0 : char *p = d_path(path, buf, size);
472 [ # # ]: 0 : if (!IS_ERR(p)) {
473 : 0 : char *end = mangle_path(buf, p, esc);
474 [ # # ]: 0 : if (end)
475 : 0 : res = end - buf;
476 : : }
477 : : }
478 [ # # ]: 0 : seq_commit(m, res);
479 : :
480 : 0 : return res;
481 : : }
482 : : EXPORT_SYMBOL(seq_path);
483 : :
484 : : /**
485 : : * seq_file_path - seq_file interface to print a pathname of a file
486 : : * @m: the seq_file handle
487 : : * @file: the struct file to print
488 : : * @esc: set of characters to escape in the output
489 : : *
490 : : * return the absolute path to the file.
491 : : */
492 : 0 : int seq_file_path(struct seq_file *m, struct file *file, const char *esc)
493 : : {
494 : 0 : return seq_path(m, &file->f_path, esc);
495 : : }
496 : : EXPORT_SYMBOL(seq_file_path);
497 : :
498 : : /*
499 : : * Same as seq_path, but relative to supplied root.
500 : : */
501 : 74177 : int seq_path_root(struct seq_file *m, const struct path *path,
502 : : const struct path *root, const char *esc)
503 : : {
504 : 74177 : char *buf;
505 [ - + ]: 74177 : size_t size = seq_get_buf(m, &buf);
506 : 74177 : int res = -ENAMETOOLONG;
507 : :
508 [ + - ]: 74177 : if (size) {
509 : 74177 : char *p;
510 : :
511 : 74177 : p = __d_path(path, root, buf, size);
512 [ + + ]: 74177 : if (!p)
513 : : return SEQ_SKIP;
514 [ + - ]: 72430 : res = PTR_ERR(p);
515 [ + - ]: 72430 : if (!IS_ERR(p)) {
516 : 72430 : char *end = mangle_path(buf, p, esc);
517 [ - + ]: 72430 : if (end)
518 : 72430 : res = end - buf;
519 : : else
520 : : res = -ENAMETOOLONG;
521 : : }
522 : : }
523 [ - + ]: 72430 : seq_commit(m, res);
524 : :
525 [ + - ]: 72430 : return res < 0 && res != -ENAMETOOLONG ? res : 0;
526 : : }
527 : :
528 : : /*
529 : : * returns the path of the 'dentry' from the root of its filesystem.
530 : : */
531 : 62182 : int seq_dentry(struct seq_file *m, struct dentry *dentry, const char *esc)
532 : : {
533 : 62182 : char *buf;
534 [ - + ]: 62182 : size_t size = seq_get_buf(m, &buf);
535 : 62182 : int res = -1;
536 : :
537 [ + - ]: 62182 : if (size) {
538 : 62182 : char *p = dentry_path(dentry, buf, size);
539 [ - + ]: 62182 : if (!IS_ERR(p)) {
540 : 62182 : char *end = mangle_path(buf, p, esc);
541 [ - + ]: 62182 : if (end)
542 : 62182 : res = end - buf;
543 : : }
544 : : }
545 [ - + ]: 62182 : seq_commit(m, res);
546 : :
547 : 62182 : return res;
548 : : }
549 : : EXPORT_SYMBOL(seq_dentry);
550 : :
551 : 17758 : static void *single_start(struct seq_file *p, loff_t *pos)
552 : : {
553 [ + + ]: 17758 : return NULL + (*pos == 0);
554 : : }
555 : :
556 : 9005 : static void *single_next(struct seq_file *p, void *v, loff_t *pos)
557 : : {
558 : 9005 : ++*pos;
559 : 9005 : return NULL;
560 : : }
561 : :
562 : 17758 : static void single_stop(struct seq_file *p, void *v)
563 : : {
564 : 17758 : }
565 : :
566 : 9005 : int single_open(struct file *file, int (*show)(struct seq_file *, void *),
567 : : void *data)
568 : : {
569 : 9005 : struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
570 : 9005 : int res = -ENOMEM;
571 : :
572 [ + - ]: 9005 : if (op) {
573 : 9005 : op->start = single_start;
574 : 9005 : op->next = single_next;
575 : 9005 : op->stop = single_stop;
576 : 9005 : op->show = show;
577 : 9005 : res = seq_open(file, op);
578 [ + - ]: 9005 : if (!res)
579 : 9005 : ((struct seq_file *)file->private_data)->private = data;
580 : : else
581 : 0 : kfree(op);
582 : : }
583 : 9005 : return res;
584 : : }
585 : : EXPORT_SYMBOL(single_open);
586 : :
587 : 0 : int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
588 : : void *data, size_t size)
589 : : {
590 : 0 : char *buf = seq_buf_alloc(size);
591 : 0 : int ret;
592 [ # # ]: 0 : if (!buf)
593 : : return -ENOMEM;
594 : 0 : ret = single_open(file, show, data);
595 [ # # ]: 0 : if (ret) {
596 : 0 : kvfree(buf);
597 : 0 : return ret;
598 : : }
599 : 0 : ((struct seq_file *)file->private_data)->buf = buf;
600 : 0 : ((struct seq_file *)file->private_data)->size = size;
601 : 0 : return 0;
602 : : }
603 : : EXPORT_SYMBOL(single_open_size);
604 : :
605 : 9005 : int single_release(struct inode *inode, struct file *file)
606 : : {
607 : 9005 : const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
608 : 9005 : int res = seq_release(inode, file);
609 : 9005 : kfree(op);
610 : 9005 : return res;
611 : : }
612 : : EXPORT_SYMBOL(single_release);
613 : :
614 : 403 : int seq_release_private(struct inode *inode, struct file *file)
615 : : {
616 : 403 : struct seq_file *seq = file->private_data;
617 : :
618 : 403 : kfree(seq->private);
619 : 403 : seq->private = NULL;
620 : 403 : return seq_release(inode, file);
621 : : }
622 : : EXPORT_SYMBOL(seq_release_private);
623 : :
624 : 424 : void *__seq_open_private(struct file *f, const struct seq_operations *ops,
625 : : int psize)
626 : : {
627 : 424 : int rc;
628 : 424 : void *private;
629 : 424 : struct seq_file *seq;
630 : :
631 : 424 : private = kzalloc(psize, GFP_KERNEL_ACCOUNT);
632 [ - + ]: 424 : if (private == NULL)
633 : 0 : goto out;
634 : :
635 : 424 : rc = seq_open(f, ops);
636 [ - + ]: 424 : if (rc < 0)
637 : 0 : goto out_free;
638 : :
639 : 424 : seq = f->private_data;
640 : 424 : seq->private = private;
641 : 424 : return private;
642 : :
643 : : out_free:
644 : 0 : kfree(private);
645 : : out:
646 : : return NULL;
647 : : }
648 : : EXPORT_SYMBOL(__seq_open_private);
649 : :
650 : 424 : int seq_open_private(struct file *filp, const struct seq_operations *ops,
651 : : int psize)
652 : : {
653 [ - + ]: 424 : return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
654 : : }
655 : : EXPORT_SYMBOL(seq_open_private);
656 : :
657 : 405237 : void seq_putc(struct seq_file *m, char c)
658 : : {
659 [ + - ]: 306464 : if (m->count >= m->size)
660 : : return;
661 : :
662 : 405237 : m->buf[m->count++] = c;
663 : : }
664 : : EXPORT_SYMBOL(seq_putc);
665 : :
666 : 450116 : void seq_puts(struct seq_file *m, const char *s)
667 : : {
668 : 450116 : int len = strlen(s);
669 : :
670 [ - + ]: 450116 : if (m->count + len >= m->size) {
671 : 0 : seq_set_overflow(m);
672 : 0 : return;
673 : : }
674 : 450116 : memcpy(m->buf + m->count, s, len);
675 : 450116 : m->count += len;
676 : : }
677 : : EXPORT_SYMBOL(seq_puts);
678 : :
679 : : /**
680 : : * A helper routine for putting decimal numbers without rich format of printf().
681 : : * only 'unsigned long long' is supported.
682 : : * @m: seq_file identifying the buffer to which data should be written
683 : : * @delimiter: a string which is printed before the number
684 : : * @num: the number
685 : : * @width: a minimum field width
686 : : *
687 : : * This routine will put strlen(delimiter) + number into seq_filed.
688 : : * This routine is very quick when you show lots of numbers.
689 : : * In usual cases, it will be better to use seq_printf(). It's easier to read.
690 : : */
691 : 86920 : void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
692 : : unsigned long long num, unsigned int width)
693 : : {
694 : 86920 : int len;
695 : :
696 [ - + ]: 86920 : if (m->count + 2 >= m->size) /* we'll write 2 bytes at least */
697 : 0 : goto overflow;
698 : :
699 [ + - + + ]: 86920 : if (delimiter && delimiter[0]) {
700 [ + + ]: 84841 : if (delimiter[1] == 0)
701 [ + - ]: 69667 : seq_putc(m, delimiter[0]);
702 : : else
703 : 15174 : seq_puts(m, delimiter);
704 : : }
705 : :
706 : 86920 : if (!width)
707 : : width = 1;
708 : :
709 [ - + ]: 86920 : if (m->count + width >= m->size)
710 : 0 : goto overflow;
711 : :
712 : 86920 : len = num_to_str(m->buf + m->count, m->size - m->count, num, width);
713 [ - + ]: 86920 : if (!len)
714 : 0 : goto overflow;
715 : :
716 : 86920 : m->count += len;
717 : 86920 : return;
718 : :
719 : 0 : overflow:
720 : 0 : seq_set_overflow(m);
721 : : }
722 : :
723 : 78976 : void seq_put_decimal_ull(struct seq_file *m, const char *delimiter,
724 : : unsigned long long num)
725 : : {
726 : 78976 : return seq_put_decimal_ull_width(m, delimiter, num, 0);
727 : : }
728 : : EXPORT_SYMBOL(seq_put_decimal_ull);
729 : :
730 : : /**
731 : : * seq_put_hex_ll - put a number in hexadecimal notation
732 : : * @m: seq_file identifying the buffer to which data should be written
733 : : * @delimiter: a string which is printed before the number
734 : : * @v: the number
735 : : * @width: a minimum field width
736 : : *
737 : : * seq_put_hex_ll(m, "", v, 8) is equal to seq_printf(m, "%08llx", v)
738 : : *
739 : : * This routine is very quick when you show lots of numbers.
740 : : * In usual cases, it will be better to use seq_printf(). It's easier to read.
741 : : */
742 : 4820 : void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
743 : : unsigned long long v, unsigned int width)
744 : : {
745 : 4820 : unsigned int len;
746 : 4820 : int i;
747 : :
748 [ - + - - ]: 4820 : if (delimiter && delimiter[0]) {
749 [ # # ]: 0 : if (delimiter[1] == 0)
750 [ # # ]: 0 : seq_putc(m, delimiter[0]);
751 : : else
752 : 0 : seq_puts(m, delimiter);
753 : : }
754 : :
755 : : /* If x is 0, the result of __builtin_clzll is undefined */
756 [ + + ]: 4820 : if (v == 0)
757 : : len = 1;
758 : : else
759 : 2892 : len = (sizeof(v) * 8 - __builtin_clzll(v) + 3) / 4;
760 : :
761 : 4820 : if (len < width)
762 : : len = width;
763 : :
764 [ - + ]: 4820 : if (m->count + len > m->size) {
765 : 0 : seq_set_overflow(m);
766 : 0 : return;
767 : : }
768 : :
769 [ + + ]: 43380 : for (i = len - 1; i >= 0; i--) {
770 : 38560 : m->buf[m->count + i] = hex_asc[0xf & v];
771 : 38560 : v = v >> 4;
772 : : }
773 : 4820 : m->count += len;
774 : : }
775 : :
776 : 29106 : void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
777 : : {
778 : 29106 : int len;
779 : :
780 [ - + ]: 29106 : if (m->count + 3 >= m->size) /* we'll write 2 bytes at least */
781 : 0 : goto overflow;
782 : :
783 [ + - + - ]: 29106 : if (delimiter && delimiter[0]) {
784 [ + - ]: 29106 : if (delimiter[1] == 0)
785 [ + - ]: 29106 : seq_putc(m, delimiter[0]);
786 : : else
787 : 0 : seq_puts(m, delimiter);
788 : : }
789 : :
790 [ - + ]: 29106 : if (m->count + 2 >= m->size)
791 : 0 : goto overflow;
792 : :
793 [ + + ]: 29106 : if (num < 0) {
794 : 2541 : m->buf[m->count++] = '-';
795 : 2541 : num = -num;
796 : : }
797 : :
798 [ + + ]: 29106 : if (num < 10) {
799 : 23665 : m->buf[m->count++] = num + '0';
800 : 23665 : return;
801 : : }
802 : :
803 : 5441 : len = num_to_str(m->buf + m->count, m->size - m->count, num, 0);
804 [ - + ]: 5441 : if (!len)
805 : 0 : goto overflow;
806 : :
807 : 5441 : m->count += len;
808 : 5441 : return;
809 : :
810 : 0 : overflow:
811 : 0 : seq_set_overflow(m);
812 : : }
813 : : EXPORT_SYMBOL(seq_put_decimal_ll);
814 : :
815 : : /**
816 : : * seq_write - write arbitrary data to buffer
817 : : * @seq: seq_file identifying the buffer to which data should be written
818 : : * @data: data address
819 : : * @len: number of bytes
820 : : *
821 : : * Return 0 on success, non-zero otherwise.
822 : : */
823 : 15372 : int seq_write(struct seq_file *seq, const void *data, size_t len)
824 : : {
825 [ + + ]: 15372 : if (seq->count + len < seq->size) {
826 : 11130 : memcpy(seq->buf + seq->count, data, len);
827 : 11130 : seq->count += len;
828 : 11130 : return 0;
829 : : }
830 : 4242 : seq_set_overflow(seq);
831 : 4242 : return -1;
832 : : }
833 : : EXPORT_SYMBOL(seq_write);
834 : :
835 : : /**
836 : : * seq_pad - write padding spaces to buffer
837 : : * @m: seq_file identifying the buffer to which data should be written
838 : : * @c: the byte to append after padding if non-zero
839 : : */
840 : 0 : void seq_pad(struct seq_file *m, char c)
841 : : {
842 : 0 : int size = m->pad_until - m->count;
843 [ # # ]: 0 : if (size > 0) {
844 [ # # ]: 0 : if (size + m->count > m->size) {
845 : 0 : seq_set_overflow(m);
846 : 0 : return;
847 : : }
848 : 0 : memset(m->buf + m->count, ' ', size);
849 : 0 : m->count += size;
850 : : }
851 [ # # ]: 0 : if (c)
852 [ # # ]: 0 : seq_putc(m, c);
853 : : }
854 : : EXPORT_SYMBOL(seq_pad);
855 : :
856 : : /* A complete analogue of print_hex_dump() */
857 : 0 : void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
858 : : int rowsize, int groupsize, const void *buf, size_t len,
859 : : bool ascii)
860 : : {
861 : 0 : const u8 *ptr = buf;
862 : 0 : int i, linelen, remaining = len;
863 : 0 : char *buffer;
864 : 0 : size_t size;
865 : 0 : int ret;
866 : :
867 [ # # ]: 0 : if (rowsize != 16 && rowsize != 32)
868 : 0 : rowsize = 16;
869 : :
870 [ # # # # ]: 0 : for (i = 0; i < len && !seq_has_overflowed(m); i += rowsize) {
871 : 0 : linelen = min(remaining, rowsize);
872 : 0 : remaining -= rowsize;
873 : :
874 [ # # # ]: 0 : switch (prefix_type) {
875 : 0 : case DUMP_PREFIX_ADDRESS:
876 : 0 : seq_printf(m, "%s%p: ", prefix_str, ptr + i);
877 : 0 : break;
878 : 0 : case DUMP_PREFIX_OFFSET:
879 : 0 : seq_printf(m, "%s%.8x: ", prefix_str, i);
880 : 0 : break;
881 : 0 : default:
882 : 0 : seq_printf(m, "%s", prefix_str);
883 : 0 : break;
884 : : }
885 : :
886 [ # # ]: 0 : size = seq_get_buf(m, &buffer);
887 : 0 : ret = hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
888 : : buffer, size, ascii);
889 [ # # # # ]: 0 : seq_commit(m, ret < size ? ret : -1);
890 : :
891 [ # # ]: 0 : seq_putc(m, '\n');
892 : : }
893 : 0 : }
894 : : EXPORT_SYMBOL(seq_hex_dump);
895 : :
896 : 1327 : struct list_head *seq_list_start(struct list_head *head, loff_t pos)
897 : : {
898 : 1327 : struct list_head *lh;
899 : :
900 [ - - + + ]: 1390 : list_for_each(lh, head)
901 [ - - + + ]: 1369 : if (pos-- == 0)
902 : 1306 : return lh;
903 : :
904 : : return NULL;
905 : : }
906 : : EXPORT_SYMBOL(seq_list_start);
907 : :
908 : 0 : struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
909 : : {
910 [ # # ]: 0 : if (!pos)
911 : : return head;
912 : :
913 : 0 : return seq_list_start(head, pos - 1);
914 : : }
915 : : EXPORT_SYMBOL(seq_list_start_head);
916 : :
917 : 74240 : struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
918 : : {
919 : 74240 : struct list_head *lh;
920 : :
921 : 74240 : lh = ((struct list_head *)v)->next;
922 : 74240 : ++*ppos;
923 [ + + ]: 74240 : return lh == head ? NULL : lh;
924 : : }
925 : : EXPORT_SYMBOL(seq_list_next);
926 : :
927 : : /**
928 : : * seq_hlist_start - start an iteration of a hlist
929 : : * @head: the head of the hlist
930 : : * @pos: the start position of the sequence
931 : : *
932 : : * Called at seq_file->op->start().
933 : : */
934 : 0 : struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
935 : : {
936 : 0 : struct hlist_node *node;
937 : :
938 [ # # # # ]: 0 : hlist_for_each(node, head)
939 [ # # # # ]: 0 : if (pos-- == 0)
940 : 0 : return node;
941 : : return NULL;
942 : : }
943 : : EXPORT_SYMBOL(seq_hlist_start);
944 : :
945 : : /**
946 : : * seq_hlist_start_head - start an iteration of a hlist
947 : : * @head: the head of the hlist
948 : : * @pos: the start position of the sequence
949 : : *
950 : : * Called at seq_file->op->start(). Call this function if you want to
951 : : * print a header at the top of the output.
952 : : */
953 : 0 : struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
954 : : {
955 [ # # ]: 0 : if (!pos)
956 : : return SEQ_START_TOKEN;
957 : :
958 : 0 : return seq_hlist_start(head, pos - 1);
959 : : }
960 : : EXPORT_SYMBOL(seq_hlist_start_head);
961 : :
962 : : /**
963 : : * seq_hlist_next - move to the next position of the hlist
964 : : * @v: the current iterator
965 : : * @head: the head of the hlist
966 : : * @ppos: the current position
967 : : *
968 : : * Called at seq_file->op->next().
969 : : */
970 : 0 : struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
971 : : loff_t *ppos)
972 : : {
973 : 0 : struct hlist_node *node = v;
974 : :
975 : 0 : ++*ppos;
976 [ # # ]: 0 : if (v == SEQ_START_TOKEN)
977 : 0 : return head->first;
978 : : else
979 : 0 : return node->next;
980 : : }
981 : : EXPORT_SYMBOL(seq_hlist_next);
982 : :
983 : : /**
984 : : * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
985 : : * @head: the head of the hlist
986 : : * @pos: the start position of the sequence
987 : : *
988 : : * Called at seq_file->op->start().
989 : : *
990 : : * This list-traversal primitive may safely run concurrently with
991 : : * the _rcu list-mutation primitives such as hlist_add_head_rcu()
992 : : * as long as the traversal is guarded by rcu_read_lock().
993 : : */
994 : 0 : struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
995 : : loff_t pos)
996 : : {
997 : 0 : struct hlist_node *node;
998 : :
999 [ # # # # ]: 0 : __hlist_for_each_rcu(node, head)
1000 [ # # # # ]: 0 : if (pos-- == 0)
1001 : 0 : return node;
1002 : : return NULL;
1003 : : }
1004 : : EXPORT_SYMBOL(seq_hlist_start_rcu);
1005 : :
1006 : : /**
1007 : : * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
1008 : : * @head: the head of the hlist
1009 : : * @pos: the start position of the sequence
1010 : : *
1011 : : * Called at seq_file->op->start(). Call this function if you want to
1012 : : * print a header at the top of the output.
1013 : : *
1014 : : * This list-traversal primitive may safely run concurrently with
1015 : : * the _rcu list-mutation primitives such as hlist_add_head_rcu()
1016 : : * as long as the traversal is guarded by rcu_read_lock().
1017 : : */
1018 : 0 : struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
1019 : : loff_t pos)
1020 : : {
1021 [ # # ]: 0 : if (!pos)
1022 : : return SEQ_START_TOKEN;
1023 : :
1024 : 0 : return seq_hlist_start_rcu(head, pos - 1);
1025 : : }
1026 : : EXPORT_SYMBOL(seq_hlist_start_head_rcu);
1027 : :
1028 : : /**
1029 : : * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
1030 : : * @v: the current iterator
1031 : : * @head: the head of the hlist
1032 : : * @ppos: the current position
1033 : : *
1034 : : * Called at seq_file->op->next().
1035 : : *
1036 : : * This list-traversal primitive may safely run concurrently with
1037 : : * the _rcu list-mutation primitives such as hlist_add_head_rcu()
1038 : : * as long as the traversal is guarded by rcu_read_lock().
1039 : : */
1040 : 0 : struct hlist_node *seq_hlist_next_rcu(void *v,
1041 : : struct hlist_head *head,
1042 : : loff_t *ppos)
1043 : : {
1044 : 0 : struct hlist_node *node = v;
1045 : :
1046 : 0 : ++*ppos;
1047 [ # # ]: 0 : if (v == SEQ_START_TOKEN)
1048 : 0 : return rcu_dereference(head->first);
1049 : : else
1050 : 0 : return rcu_dereference(node->next);
1051 : : }
1052 : : EXPORT_SYMBOL(seq_hlist_next_rcu);
1053 : :
1054 : : /**
1055 : : * seq_hlist_start_precpu - start an iteration of a percpu hlist array
1056 : : * @head: pointer to percpu array of struct hlist_heads
1057 : : * @cpu: pointer to cpu "cursor"
1058 : : * @pos: start position of sequence
1059 : : *
1060 : : * Called at seq_file->op->start().
1061 : : */
1062 : : struct hlist_node *
1063 : 0 : seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
1064 : : {
1065 : 0 : struct hlist_node *node;
1066 : :
1067 [ # # ]: 0 : for_each_possible_cpu(*cpu) {
1068 [ # # ]: 0 : hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
1069 [ # # ]: 0 : if (pos-- == 0)
1070 : 0 : return node;
1071 : : }
1072 : : }
1073 : : return NULL;
1074 : : }
1075 : : EXPORT_SYMBOL(seq_hlist_start_percpu);
1076 : :
1077 : : /**
1078 : : * seq_hlist_next_percpu - move to the next position of the percpu hlist array
1079 : : * @v: pointer to current hlist_node
1080 : : * @head: pointer to percpu array of struct hlist_heads
1081 : : * @cpu: pointer to cpu "cursor"
1082 : : * @pos: start position of sequence
1083 : : *
1084 : : * Called at seq_file->op->next().
1085 : : */
1086 : : struct hlist_node *
1087 : 0 : seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
1088 : : int *cpu, loff_t *pos)
1089 : : {
1090 : 0 : struct hlist_node *node = v;
1091 : :
1092 : 0 : ++*pos;
1093 : :
1094 [ # # ]: 0 : if (node->next)
1095 : : return node->next;
1096 : :
1097 [ # # ]: 0 : for (*cpu = cpumask_next(*cpu, cpu_possible_mask); *cpu < nr_cpu_ids;
1098 : 0 : *cpu = cpumask_next(*cpu, cpu_possible_mask)) {
1099 : 0 : struct hlist_head *bucket = per_cpu_ptr(head, *cpu);
1100 : :
1101 [ # # ]: 0 : if (!hlist_empty(bucket))
1102 : 0 : return bucket->first;
1103 : : }
1104 : : return NULL;
1105 : : }
1106 : : EXPORT_SYMBOL(seq_hlist_next_percpu);
1107 : :
1108 : 21 : void __init seq_file_init(void)
1109 : : {
1110 : 21 : seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT|SLAB_PANIC);
1111 : 21 : }
|