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