Blame view

fs/seq_file.c 26.1 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  /*
   * linux/fs/seq_file.c
   *
   * helper functions for making synthetic files from sequences of records.
   * initial implementation -- AV, Oct 2001.
   */
a39630157   Joe Perches   fs/seq_file.c: se...
8
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
096523203   Alexey Dobriyan   seq_file: allocat...
9
  #include <linux/cache.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/fs.h>
630d9c472   Paul Gortmaker   fs: reduce the us...
11
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/seq_file.h>
058504edd   Heiko Carstens   fs/seq_file: fall...
13
  #include <linux/vmalloc.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/slab.h>
adb37c4c6   Eric W. Biederman   userns: Make seq_...
15
  #include <linux/cred.h>
058504edd   Heiko Carstens   fs/seq_file: fall...
16
  #include <linux/mm.h>
37607102c   Andy Shevchenko   seq_file: provide...
17
  #include <linux/printk.h>
25c6bb76e   Andy Shevchenko   seq_file: reuse s...
18
  #include <linux/string_helpers.h>
d4d50710a   Christoph Hellwig   seq_file: add seq...
19
  #include <linux/uio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
21
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/page.h>
096523203   Alexey Dobriyan   seq_file: allocat...
23
  static struct kmem_cache *seq_file_cache __ro_after_init;
e075f5915   KAMEZAWA Hiroyuki   seq_file: add seq...
24
25
26
27
  static void seq_set_overflow(struct seq_file *m)
  {
  	m->count = m->size;
  }
058504edd   Heiko Carstens   fs/seq_file: fall...
28
29
  static void *seq_buf_alloc(unsigned long size)
  {
8cae8cd89   Eric Sandeen   seq_file: disallo...
30
31
  	if (unlikely(size > MAX_RW_COUNT))
  		return NULL;
d64d01a15   Alexey Dobriyan   seq_file: account...
32
  	return kvmalloc(size, GFP_KERNEL_ACCOUNT);
058504edd   Heiko Carstens   fs/seq_file: fall...
33
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
42
43
44
45
  /**
   *	seq_open -	initialize sequential file
   *	@file: file we initialize
   *	@op: method table describing the sequence
   *
   *	seq_open() sets @file, associating it with a sequence described
   *	by @op.  @op->start() sets the iterator up and returns the first
   *	element of sequence. @op->stop() shuts it down.  @op->next()
   *	returns the next element of sequence.  @op->show() prints element
   *	into the buffer.  In case of error ->start() and ->next() return
   *	ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
   *	returns 0 in case of success and negative number in case of error.
521b5d0c4   Al Viro   [PATCH] teach seq...
46
   *	Returning SEQ_SKIP means "discard this element and move on".
460b865e5   Yann Droneaud   fs: document seq_...
47
48
   *	Note: seq_open() will allocate a struct seq_file and store its
   *	pointer in @file->private_data. This pointer should not be modified.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
   */
15ad7cdcf   Helge Deller   [PATCH] struct se...
50
  int seq_open(struct file *file, const struct seq_operations *op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  {
189f9841d   Yann Droneaud   fs: allocate stru...
52
53
54
  	struct seq_file *p;
  
  	WARN_ON(file->private_data);
096523203   Alexey Dobriyan   seq_file: allocat...
55
  	p = kmem_cache_zalloc(seq_file_cache, GFP_KERNEL);
189f9841d   Yann Droneaud   fs: allocate stru...
56
57
58
59
  	if (!p)
  		return -ENOMEM;
  
  	file->private_data = p;
1abe77b0f   Al Viro   [PATCH] allow cal...
60

0ac1759ab   Ingo Molnar   [PATCH] sem2mutex...
61
  	mutex_init(&p->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  	p->op = op;
34dbbcdbf   Linus Torvalds   Make file credent...
63
64
65
66
  
  	// No refcounting: the lifetime of 'p' is constrained
  	// to the lifetime of the file.
  	p->file = file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
  
  	/*
8f19d4729   Eric Biederman   seq_file: properl...
69
70
71
72
73
74
75
76
77
  	 * seq_files support lseek() and pread().  They do not implement
  	 * write() at all, but we clear FMODE_PWRITE here for historical
  	 * reasons.
  	 *
  	 * If a client of seq_files a) implements file.write() and b) wishes to
  	 * support pwrite() then that client will need to implement its own
  	 * file.open() which calls seq_open() and then sets FMODE_PWRITE.
  	 */
  	file->f_mode &= ~FMODE_PWRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
  	return 0;
  }
  EXPORT_SYMBOL(seq_open);
33da8892a   Eric Biederman   seq_file: move tr...
81
82
  static int traverse(struct seq_file *m, loff_t offset)
  {
1f4aace60   NeilBrown   fs/seq_file.c: si...
83
  	loff_t pos = 0;
33da8892a   Eric Biederman   seq_file: move tr...
84
85
  	int error = 0;
  	void *p;
1f4aace60   NeilBrown   fs/seq_file.c: si...
86
  	m->index = 0;
33da8892a   Eric Biederman   seq_file: move tr...
87
  	m->count = m->from = 0;
1f4aace60   NeilBrown   fs/seq_file.c: si...
88
  	if (!offset)
33da8892a   Eric Biederman   seq_file: move tr...
89
  		return 0;
1f4aace60   NeilBrown   fs/seq_file.c: si...
90

33da8892a   Eric Biederman   seq_file: move tr...
91
  	if (!m->buf) {
058504edd   Heiko Carstens   fs/seq_file: fall...
92
  		m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
33da8892a   Eric Biederman   seq_file: move tr...
93
94
95
  		if (!m->buf)
  			return -ENOMEM;
  	}
1f4aace60   NeilBrown   fs/seq_file.c: si...
96
  	p = m->op->start(m, &m->index);
33da8892a   Eric Biederman   seq_file: move tr...
97
98
99
100
101
102
103
104
105
106
107
  	while (p) {
  		error = PTR_ERR(p);
  		if (IS_ERR(p))
  			break;
  		error = m->op->show(m, p);
  		if (error < 0)
  			break;
  		if (unlikely(error)) {
  			error = 0;
  			m->count = 0;
  		}
1f33c41c0   Joe Perches   seq_file: Rename ...
108
  		if (seq_has_overflowed(m))
33da8892a   Eric Biederman   seq_file: move tr...
109
  			goto Eoverflow;
6a2aeab59   NeilBrown   seq_file: fix pro...
110
  		p = m->op->next(m, p, &m->index);
33da8892a   Eric Biederman   seq_file: move tr...
111
112
113
  		if (pos + m->count > offset) {
  			m->from = offset - pos;
  			m->count -= m->from;
33da8892a   Eric Biederman   seq_file: move tr...
114
115
116
117
  			break;
  		}
  		pos += m->count;
  		m->count = 0;
1f4aace60   NeilBrown   fs/seq_file.c: si...
118
  		if (pos == offset)
33da8892a   Eric Biederman   seq_file: move tr...
119
  			break;
33da8892a   Eric Biederman   seq_file: move tr...
120
121
122
123
124
125
  	}
  	m->op->stop(m, p);
  	return error;
  
  Eoverflow:
  	m->op->stop(m, p);
058504edd   Heiko Carstens   fs/seq_file: fall...
126
  	kvfree(m->buf);
801a76050   Al Viro   seq_file: always ...
127
  	m->count = 0;
058504edd   Heiko Carstens   fs/seq_file: fall...
128
  	m->buf = seq_buf_alloc(m->size <<= 1);
33da8892a   Eric Biederman   seq_file: move tr...
129
130
  	return !m->buf ? -ENOMEM : -EAGAIN;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
  /**
   *	seq_read -	->read() method for sequential files.
67be2dd1b   Martin Waitz   [PATCH] DocBook: ...
133
134
135
136
   *	@file: the file to read from
   *	@buf: the buffer to read to
   *	@size: the maximum number of bytes to read
   *	@ppos: the current position in the file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
   *
   *	Ready-made ->f_op->read()
   */
  ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
  {
d4d50710a   Christoph Hellwig   seq_file: add seq...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  	struct iovec iov = { .iov_base = buf, .iov_len = size};
  	struct kiocb kiocb;
  	struct iov_iter iter;
  	ssize_t ret;
  
  	init_sync_kiocb(&kiocb, file);
  	iov_iter_init(&iter, READ, &iov, 1, size);
  
  	kiocb.ki_pos = *ppos;
  	ret = seq_read_iter(&kiocb, &iter);
  	*ppos = kiocb.ki_pos;
  	return ret;
  }
  EXPORT_SYMBOL(seq_read);
  
  /*
   * Ready-made ->f_op->read_iter()
   */
  ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
  {
  	struct seq_file *m = iocb->ki_filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  	size_t copied = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
  	size_t n;
  	void *p;
  	int err = 0;
4bbf439b0   Al Viro   fix return values...
167
168
  	if (!iov_iter_count(iter))
  		return 0;
0ac1759ab   Ingo Molnar   [PATCH] sem2mutex...
169
  	mutex_lock(&m->lock);
8f19d4729   Eric Biederman   seq_file: properl...
170

7904ac842   Earl Chew   seq_file: fix mis...
171
  	/*
e522751d6   Tomasz Majchrzak   seq_file: reset i...
172
173
174
  	 * if request is to read from zero offset, reset iterator to first
  	 * record as it might have been already advanced by previous requests
  	 */
d4d50710a   Christoph Hellwig   seq_file: add seq...
175
  	if (iocb->ki_pos == 0) {
e522751d6   Tomasz Majchrzak   seq_file: reset i...
176
  		m->index = 0;
cf5eebae2   Miklos Szeredi   seq_file: fix inc...
177
178
  		m->count = 0;
  	}
e522751d6   Tomasz Majchrzak   seq_file: reset i...
179

d4d50710a   Christoph Hellwig   seq_file: add seq...
180
181
182
  	/* Don't assume ki_pos is where we left it */
  	if (unlikely(iocb->ki_pos != m->read_pos)) {
  		while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
8f19d4729   Eric Biederman   seq_file: properl...
183
184
185
186
  			;
  		if (err) {
  			/* With prejudice... */
  			m->read_pos = 0;
8f19d4729   Eric Biederman   seq_file: properl...
187
188
189
  			m->index = 0;
  			m->count = 0;
  			goto Done;
7904ac842   Earl Chew   seq_file: fix mis...
190
  		} else {
d4d50710a   Christoph Hellwig   seq_file: add seq...
191
  			m->read_pos = iocb->ki_pos;
8f19d4729   Eric Biederman   seq_file: properl...
192
193
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  	/* grab buffer if we didn't have one */
  	if (!m->buf) {
058504edd   Heiko Carstens   fs/seq_file: fall...
196
  		m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
  		if (!m->buf)
  			goto Enomem;
  	}
4bbf439b0   Al Viro   fix return values...
200
  	// something left in the buffer - copy it out first
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  	if (m->count) {
4bbf439b0   Al Viro   fix return values...
202
  		n = copy_to_iter(m->buf + m->from, m->count, iter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  		m->count -= n;
  		m->from += n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  		copied += n;
4bbf439b0   Al Viro   fix return values...
206
  		if (m->count)	// hadn't managed to copy everything
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  			goto Done;
  	}
4bbf439b0   Al Viro   fix return values...
209
  	// get a non-empty record in the buffer
1f4aace60   NeilBrown   fs/seq_file.c: si...
210
211
  	m->from = 0;
  	p = m->op->start(m, &m->index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	while (1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  		err = PTR_ERR(p);
4bbf439b0   Al Viro   fix return values...
214
  		if (!p || IS_ERR(p))	// EOF or an error
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
  			break;
  		err = m->op->show(m, p);
4bbf439b0   Al Viro   fix return values...
217
  		if (err < 0)		// hard error
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  			break;
4bbf439b0   Al Viro   fix return values...
219
  		if (unlikely(err))	// ->show() says "skip it"
521b5d0c4   Al Viro   [PATCH] teach seq...
220
  			m->count = 0;
4bbf439b0   Al Viro   fix return values...
221
  		if (unlikely(!m->count)) { // empty record
1f4aace60   NeilBrown   fs/seq_file.c: si...
222
  			p = m->op->next(m, p, &m->index);
4cdfe84b5   Al Viro   [PATCH] deal with...
223
224
  			continue;
  		}
4bbf439b0   Al Viro   fix return values...
225
  		if (!seq_has_overflowed(m)) // got it
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  			goto Fill;
4bbf439b0   Al Viro   fix return values...
227
  		// need a bigger buffer
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		m->op->stop(m, p);
058504edd   Heiko Carstens   fs/seq_file: fall...
229
  		kvfree(m->buf);
801a76050   Al Viro   seq_file: always ...
230
  		m->count = 0;
058504edd   Heiko Carstens   fs/seq_file: fall...
231
  		m->buf = seq_buf_alloc(m->size <<= 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  		if (!m->buf)
  			goto Enomem;
1f4aace60   NeilBrown   fs/seq_file.c: si...
234
  		p = m->op->start(m, &m->index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  	}
4bbf439b0   Al Viro   fix return values...
236
  	// EOF or an error
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
  	m->op->stop(m, p);
  	m->count = 0;
  	goto Done;
  Fill:
4bbf439b0   Al Viro   fix return values...
241
242
243
  	// one non-empty record is in the buffer; if they want more,
  	// try to fit more in, but in any case we need to advance
  	// the iterator once for every record shown.
1f4aace60   NeilBrown   fs/seq_file.c: si...
244
  	while (1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  		size_t offs = m->count;
1f4aace60   NeilBrown   fs/seq_file.c: si...
246
247
248
  		loff_t pos = m->index;
  
  		p = m->op->next(m, p, &m->index);
3bfa7e141   Vasily Averin   fs/seq_file.c: se...
249
  		if (pos == m->index) {
a39630157   Joe Perches   fs/seq_file.c: se...
250
251
252
  			pr_info_ratelimited("buggy .next function %ps did not update position index
  ",
  					    m->op->next);
1f4aace60   NeilBrown   fs/seq_file.c: si...
253
  			m->index++;
3bfa7e141   Vasily Averin   fs/seq_file.c: se...
254
  		}
4bbf439b0   Al Viro   fix return values...
255
  		if (!p || IS_ERR(p))	// no next record for us
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  			break;
4bbf439b0   Al Viro   fix return values...
257
  		if (m->count >= iov_iter_count(iter))
1f4aace60   NeilBrown   fs/seq_file.c: si...
258
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  		err = m->op->show(m, p);
4bbf439b0   Al Viro   fix return values...
260
  		if (err > 0) {		// ->show() says "skip it"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  			m->count = offs;
4bbf439b0   Al Viro   fix return values...
262
263
264
  		} else if (err || seq_has_overflowed(m)) {
  			m->count = offs;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  	}
  	m->op->stop(m, p);
4bbf439b0   Al Viro   fix return values...
268
  	n = copy_to_iter(m->buf, m->count, iter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	copied += n;
  	m->count -= n;
1f4aace60   NeilBrown   fs/seq_file.c: si...
271
  	m->from = n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  Done:
4bbf439b0   Al Viro   fix return values...
273
274
275
  	if (unlikely(!copied)) {
  		copied = m->count ? -EFAULT : err;
  	} else {
d4d50710a   Christoph Hellwig   seq_file: add seq...
276
  		iocb->ki_pos += copied;
8f19d4729   Eric Biederman   seq_file: properl...
277
278
  		m->read_pos += copied;
  	}
0ac1759ab   Ingo Molnar   [PATCH] sem2mutex...
279
  	mutex_unlock(&m->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
  	return copied;
  Enomem:
  	err = -ENOMEM;
  	goto Done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  }
d4d50710a   Christoph Hellwig   seq_file: add seq...
285
  EXPORT_SYMBOL(seq_read_iter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
  /**
   *	seq_lseek -	->llseek() method for sequential files.
67be2dd1b   Martin Waitz   [PATCH] DocBook: ...
289
290
   *	@file: the file in question
   *	@offset: new position
254adaa46   Randy Dunlap   seq_file: fix new...
291
   *	@whence: 0 for absolute, 1 for relative position
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
   *
   *	Ready-made ->f_op->llseek()
   */
965c8e59c   Andrew Morton   lseek: the "whenc...
295
  loff_t seq_lseek(struct file *file, loff_t offset, int whence)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  {
8209e2f46   Joe Perches   fs/seq_file.c: Re...
297
  	struct seq_file *m = file->private_data;
16abef0e9   David Sterba   fs: use loff_t ty...
298
  	loff_t retval = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

0ac1759ab   Ingo Molnar   [PATCH] sem2mutex...
300
  	mutex_lock(&m->lock);
965c8e59c   Andrew Morton   lseek: the "whenc...
301
  	switch (whence) {
5e62adef9   Andrew Morton   fs/seq_file.c:seq...
302
303
  	case SEEK_CUR:
  		offset += file->f_pos;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
304
  		fallthrough;
5e62adef9   Andrew Morton   fs/seq_file.c:seq...
305
306
307
308
309
310
311
312
313
314
315
  	case SEEK_SET:
  		if (offset < 0)
  			break;
  		retval = offset;
  		if (offset != m->read_pos) {
  			while ((retval = traverse(m, offset)) == -EAGAIN)
  				;
  			if (retval) {
  				/* with extreme prejudice... */
  				file->f_pos = 0;
  				m->read_pos = 0;
5e62adef9   Andrew Morton   fs/seq_file.c:seq...
316
317
318
319
320
  				m->index = 0;
  				m->count = 0;
  			} else {
  				m->read_pos = offset;
  				retval = file->f_pos = offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  			}
05e16745c   Gu Zheng   seq_file: always ...
322
323
  		} else {
  			file->f_pos = offset;
5e62adef9   Andrew Morton   fs/seq_file.c:seq...
324
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	}
00c5746da   Alexey Dobriyan   mutex_unlock() la...
326
  	mutex_unlock(&m->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
333
  	return retval;
  }
  EXPORT_SYMBOL(seq_lseek);
  
  /**
   *	seq_release -	free the structures associated with sequential file.
   *	@file: file in question
6131ffaa1   Al Viro   more file_inode()...
334
   *	@inode: its inode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
   *
   *	Frees the structures associated with sequential file; can be used
   *	as ->f_op->release() if you don't have private data to destroy.
   */
  int seq_release(struct inode *inode, struct file *file)
  {
8209e2f46   Joe Perches   fs/seq_file.c: Re...
341
  	struct seq_file *m = file->private_data;
058504edd   Heiko Carstens   fs/seq_file: fall...
342
  	kvfree(m->buf);
096523203   Alexey Dobriyan   seq_file: allocat...
343
  	kmem_cache_free(seq_file_cache, m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
347
348
  	return 0;
  }
  EXPORT_SYMBOL(seq_release);
  
  /**
1d31aa172   Andy Shevchenko   seq_file: introdu...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
   * seq_escape_mem - print data into buffer, escaping some characters
   * @m: target buffer
   * @src: source buffer
   * @len: size of source buffer
   * @flags: flags to pass to string_escape_mem()
   * @esc: set of characters that need escaping
   *
   * Puts data into buffer, replacing each occurrence of character from
   * given class (defined by @flags and @esc) with printable escaped sequence.
   *
   * Use seq_has_overflowed() to check for errors.
   */
  void seq_escape_mem(struct seq_file *m, const char *src, size_t len,
  		    unsigned int flags, const char *esc)
  {
  	char *buf;
  	size_t size = seq_get_buf(m, &buf);
  	int ret;
  
  	ret = string_escape_mem(src, len, buf, size, flags, esc);
  	seq_commit(m, ret < size ? ret : -1);
  }
  EXPORT_SYMBOL(seq_escape_mem);
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
377
378
379
   *	seq_escape -	print string into buffer, escaping some characters
   *	@m:	target buffer
   *	@s:	string
   *	@esc:	set of characters that need escaping
   *
   *	Puts string into buffer, replacing each occurrence of character from
6798a8caa   Joe Perches   fs/seq_file: conv...
380
381
   *	@esc with usual octal escape.
   *	Use seq_has_overflowed() to check for errors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
   */
6798a8caa   Joe Perches   fs/seq_file: conv...
383
  void seq_escape(struct seq_file *m, const char *s, const char *esc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  {
fc3de02ea   Andy Shevchenko   seq_file: convert...
385
  	seq_escape_str(m, s, ESCAPE_OCTAL, esc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  }
  EXPORT_SYMBOL(seq_escape);
6798a8caa   Joe Perches   fs/seq_file: conv...
388
  void seq_vprintf(struct seq_file *m, const char *f, va_list args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
  	int len;
  
  	if (m->count < m->size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  		len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
  		if (m->count + len < m->size) {
  			m->count += len;
6798a8caa   Joe Perches   fs/seq_file: conv...
396
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
  		}
  	}
e075f5915   KAMEZAWA Hiroyuki   seq_file: add seq...
399
  	seq_set_overflow(m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
  }
a4808147d   Steven Whitehouse   seq_file: Add seq...
401
  EXPORT_SYMBOL(seq_vprintf);
6798a8caa   Joe Perches   fs/seq_file: conv...
402
  void seq_printf(struct seq_file *m, const char *f, ...)
a4808147d   Steven Whitehouse   seq_file: Add seq...
403
  {
a4808147d   Steven Whitehouse   seq_file: Add seq...
404
405
406
  	va_list args;
  
  	va_start(args, f);
6798a8caa   Joe Perches   fs/seq_file: conv...
407
  	seq_vprintf(m, f, args);
a4808147d   Steven Whitehouse   seq_file: Add seq...
408
  	va_end(args);
a4808147d   Steven Whitehouse   seq_file: Add seq...
409
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
  EXPORT_SYMBOL(seq_printf);
76d6a1338   Florent Revest   seq_file: Add a s...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  #ifdef CONFIG_BINARY_PRINTF
  void seq_bprintf(struct seq_file *m, const char *f, const u32 *binary)
  {
  	int len;
  
  	if (m->count < m->size) {
  		len = bstr_printf(m->buf + m->count, m->size - m->count, f,
  				  binary);
  		if (m->count + len < m->size) {
  			m->count += len;
  			return;
  		}
  	}
  	seq_set_overflow(m);
  }
  EXPORT_SYMBOL(seq_bprintf);
  #endif /* CONFIG_BINARY_PRINTF */
74e2f334f   Török Edwin   vfs, seqfile: mak...
428
  /**
958086d17   Török Edwin   vfs, seqfile: fix...
429
430
431
432
   *	mangle_path -	mangle and copy path to buffer beginning
   *	@s: buffer start
   *	@p: beginning of path in above buffer
   *	@esc: set of characters that need escaping
74e2f334f   Török Edwin   vfs, seqfile: mak...
433
434
435
436
437
438
   *
   *      Copy the path from @p to @s, replacing each occurrence of character from
   *      @esc with usual octal escape.
   *      Returns pointer past last written character in @s, or NULL in case of
   *      failure.
   */
8c9379e97   Al Viro   constify seq_file...
439
  char *mangle_path(char *s, const char *p, const char *esc)
6092d0481   Ram Pai   [patch 1/7] vfs: ...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  {
  	while (s <= p) {
  		char c = *p++;
  		if (!c) {
  			return s;
  		} else if (!strchr(esc, c)) {
  			*s++ = c;
  		} else if (s + 4 > p) {
  			break;
  		} else {
  			*s++ = '\\';
  			*s++ = '0' + ((c & 0300) >> 6);
  			*s++ = '0' + ((c & 070) >> 3);
  			*s++ = '0' + (c & 07);
  		}
  	}
  	return NULL;
  }
604094f46   Ingo Molnar   vfs, seqfile: exp...
458
  EXPORT_SYMBOL(mangle_path);
6092d0481   Ram Pai   [patch 1/7] vfs: ...
459

52afeefb9   Arjan van de Ven   expand some comme...
460
461
462
463
464
465
466
467
  /**
   * seq_path - seq_file interface to print a pathname
   * @m: the seq_file handle
   * @path: the struct path to print
   * @esc: set of characters to escape in the output
   *
   * return the absolute path of 'path', as represented by the
   * dentry / mnt pair in the path parameter.
6092d0481   Ram Pai   [patch 1/7] vfs: ...
468
   */
8c9379e97   Al Viro   constify seq_file...
469
  int seq_path(struct seq_file *m, const struct path *path, const char *esc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
471
472
473
474
475
476
  	char *buf;
  	size_t size = seq_get_buf(m, &buf);
  	int res = -1;
  
  	if (size) {
  		char *p = d_path(path, buf, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  		if (!IS_ERR(p)) {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
478
479
480
  			char *end = mangle_path(buf, p, esc);
  			if (end)
  				res = end - buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
  		}
  	}
f84398068   Miklos Szeredi   vfs: seq_file: ad...
483
484
485
  	seq_commit(m, res);
  
  	return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  }
  EXPORT_SYMBOL(seq_path);
2726d5662   Miklos Szeredi   vfs: add seq_file...
488
489
490
491
492
493
494
495
496
497
498
499
500
  /**
   * seq_file_path - seq_file interface to print a pathname of a file
   * @m: the seq_file handle
   * @file: the struct file to print
   * @esc: set of characters to escape in the output
   *
   * return the absolute path to the file.
   */
  int seq_file_path(struct seq_file *m, struct file *file, const char *esc)
  {
  	return seq_path(m, &file->f_path, esc);
  }
  EXPORT_SYMBOL(seq_file_path);
6092d0481   Ram Pai   [patch 1/7] vfs: ...
501
  /*
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
502
   * Same as seq_path, but relative to supplied root.
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
503
   */
8c9379e97   Al Viro   constify seq_file...
504
505
  int seq_path_root(struct seq_file *m, const struct path *path,
  		  const struct path *root, const char *esc)
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
506
  {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
507
508
509
510
511
  	char *buf;
  	size_t size = seq_get_buf(m, &buf);
  	int res = -ENAMETOOLONG;
  
  	if (size) {
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
512
  		char *p;
f84398068   Miklos Szeredi   vfs: seq_file: ad...
513
  		p = __d_path(path, root, buf, size);
02125a826   Al Viro   fix apparmor dere...
514
515
  		if (!p)
  			return SEQ_SKIP;
f84398068   Miklos Szeredi   vfs: seq_file: ad...
516
  		res = PTR_ERR(p);
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
517
  		if (!IS_ERR(p)) {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
518
519
520
521
522
  			char *end = mangle_path(buf, p, esc);
  			if (end)
  				res = end - buf;
  			else
  				res = -ENAMETOOLONG;
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
523
524
  		}
  	}
f84398068   Miklos Szeredi   vfs: seq_file: ad...
525
  	seq_commit(m, res);
02125a826   Al Viro   fix apparmor dere...
526
  	return res < 0 && res != -ENAMETOOLONG ? res : 0;
9d1bc6013   Miklos Szeredi   [patch 2/7] vfs: ...
527
528
529
  }
  
  /*
6092d0481   Ram Pai   [patch 1/7] vfs: ...
530
531
   * returns the path of the 'dentry' from the root of its filesystem.
   */
8c9379e97   Al Viro   constify seq_file...
532
  int seq_dentry(struct seq_file *m, struct dentry *dentry, const char *esc)
6092d0481   Ram Pai   [patch 1/7] vfs: ...
533
  {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
534
535
536
537
538
539
  	char *buf;
  	size_t size = seq_get_buf(m, &buf);
  	int res = -1;
  
  	if (size) {
  		char *p = dentry_path(dentry, buf, size);
6092d0481   Ram Pai   [patch 1/7] vfs: ...
540
  		if (!IS_ERR(p)) {
f84398068   Miklos Szeredi   vfs: seq_file: ad...
541
542
543
  			char *end = mangle_path(buf, p, esc);
  			if (end)
  				res = end - buf;
6092d0481   Ram Pai   [patch 1/7] vfs: ...
544
545
  		}
  	}
f84398068   Miklos Szeredi   vfs: seq_file: ad...
546
547
548
  	seq_commit(m, res);
  
  	return res;
6092d0481   Ram Pai   [patch 1/7] vfs: ...
549
  }
c8d3fe028   Omar Sandoval   Btrfs: show subvo...
550
  EXPORT_SYMBOL(seq_dentry);
6092d0481   Ram Pai   [patch 1/7] vfs: ...
551

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  static void *single_start(struct seq_file *p, loff_t *pos)
  {
  	return NULL + (*pos == 0);
  }
  
  static void *single_next(struct seq_file *p, void *v, loff_t *pos)
  {
  	++*pos;
  	return NULL;
  }
  
  static void single_stop(struct seq_file *p, void *v)
  {
  }
  
  int single_open(struct file *file, int (*show)(struct seq_file *, void *),
  		void *data)
  {
d64d01a15   Alexey Dobriyan   seq_file: account...
570
  	struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  	int res = -ENOMEM;
  
  	if (op) {
  		op->start = single_start;
  		op->next = single_next;
  		op->stop = single_stop;
  		op->show = show;
  		res = seq_open(file, op);
  		if (!res)
  			((struct seq_file *)file->private_data)->private = data;
  		else
  			kfree(op);
  	}
  	return res;
  }
  EXPORT_SYMBOL(single_open);
2043f495c   Al Viro   new helper: singl...
587
588
589
  int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
  		void *data, size_t size)
  {
058504edd   Heiko Carstens   fs/seq_file: fall...
590
  	char *buf = seq_buf_alloc(size);
2043f495c   Al Viro   new helper: singl...
591
592
593
594
595
  	int ret;
  	if (!buf)
  		return -ENOMEM;
  	ret = single_open(file, show, data);
  	if (ret) {
058504edd   Heiko Carstens   fs/seq_file: fall...
596
  		kvfree(buf);
2043f495c   Al Viro   new helper: singl...
597
598
599
600
601
602
603
  		return ret;
  	}
  	((struct seq_file *)file->private_data)->buf = buf;
  	((struct seq_file *)file->private_data)->size = size;
  	return 0;
  }
  EXPORT_SYMBOL(single_open_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
  int single_release(struct inode *inode, struct file *file)
  {
15ad7cdcf   Helge Deller   [PATCH] struct se...
606
  	const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  	int res = seq_release(inode, file);
  	kfree(op);
  	return res;
  }
  EXPORT_SYMBOL(single_release);
  
  int seq_release_private(struct inode *inode, struct file *file)
  {
  	struct seq_file *seq = file->private_data;
  
  	kfree(seq->private);
  	seq->private = NULL;
  	return seq_release(inode, file);
  }
  EXPORT_SYMBOL(seq_release_private);
39699037a   Pavel Emelyanov   [FS] seq_file: In...
622
623
624
625
626
627
  void *__seq_open_private(struct file *f, const struct seq_operations *ops,
  		int psize)
  {
  	int rc;
  	void *private;
  	struct seq_file *seq;
d64d01a15   Alexey Dobriyan   seq_file: account...
628
  	private = kzalloc(psize, GFP_KERNEL_ACCOUNT);
39699037a   Pavel Emelyanov   [FS] seq_file: In...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  	if (private == NULL)
  		goto out;
  
  	rc = seq_open(f, ops);
  	if (rc < 0)
  		goto out_free;
  
  	seq = f->private_data;
  	seq->private = private;
  	return private;
  
  out_free:
  	kfree(private);
  out:
  	return NULL;
  }
  EXPORT_SYMBOL(__seq_open_private);
  
  int seq_open_private(struct file *filp, const struct seq_operations *ops,
  		int psize)
  {
  	return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
  }
  EXPORT_SYMBOL(seq_open_private);
6798a8caa   Joe Perches   fs/seq_file: conv...
653
  void seq_putc(struct seq_file *m, char c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  {
6798a8caa   Joe Perches   fs/seq_file: conv...
655
656
657
658
  	if (m->count >= m->size)
  		return;
  
  	m->buf[m->count++] = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
  }
  EXPORT_SYMBOL(seq_putc);
6798a8caa   Joe Perches   fs/seq_file: conv...
661
  void seq_puts(struct seq_file *m, const char *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
  {
  	int len = strlen(s);
6798a8caa   Joe Perches   fs/seq_file: conv...
664
665
666
667
  
  	if (m->count + len >= m->size) {
  		seq_set_overflow(m);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
  	}
6798a8caa   Joe Perches   fs/seq_file: conv...
669
670
  	memcpy(m->buf + m->count, s, len);
  	m->count += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
  }
  EXPORT_SYMBOL(seq_puts);
bcf67e162   Pavel Emelianov   Make common helpe...
673

d1be35cb6   Andrei Vagin   proc: add seq_put...
674
  /**
961f3c898   Mauro Carvalho Chehab   fs: fix kernel-do...
675
676
   * seq_put_decimal_ull_width - A helper routine for putting decimal numbers
   * 			       without rich format of printf().
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
677
   * only 'unsigned long long' is supported.
d1be35cb6   Andrei Vagin   proc: add seq_put...
678
679
680
681
682
683
   * @m: seq_file identifying the buffer to which data should be written
   * @delimiter: a string which is printed before the number
   * @num: the number
   * @width: a minimum field width
   *
   * This routine will put strlen(delimiter) + number into seq_filed.
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
684
685
686
   * This routine is very quick when you show lots of numbers.
   * In usual cases, it will be better to use seq_printf(). It's easier to read.
   */
d1be35cb6   Andrei Vagin   proc: add seq_put...
687
688
  void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
  			 unsigned long long num, unsigned int width)
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
689
690
691
692
693
  {
  	int len;
  
  	if (m->count + 2 >= m->size) /* we'll write 2 bytes at least */
  		goto overflow;
48dffbf82   Andrei Vagin   proc: optimize si...
694
695
696
697
698
699
  	if (delimiter && delimiter[0]) {
  		if (delimiter[1] == 0)
  			seq_putc(m, delimiter[0]);
  		else
  			seq_puts(m, delimiter);
  	}
75ba1d07f   Joe Perches   seq/proc: modify ...
700

d1be35cb6   Andrei Vagin   proc: add seq_put...
701
702
703
704
  	if (!width)
  		width = 1;
  
  	if (m->count + width >= m->size)
75ba1d07f   Joe Perches   seq/proc: modify ...
705
  		goto overflow;
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
706

d1be35cb6   Andrei Vagin   proc: add seq_put...
707
  	len = num_to_str(m->buf + m->count, m->size - m->count, num, width);
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
708
709
  	if (!len)
  		goto overflow;
75ba1d07f   Joe Perches   seq/proc: modify ...
710

1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
711
  	m->count += len;
6798a8caa   Joe Perches   fs/seq_file: conv...
712
  	return;
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
713
  overflow:
e075f5915   KAMEZAWA Hiroyuki   seq_file: add seq...
714
  	seq_set_overflow(m);
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
715
  }
d1be35cb6   Andrei Vagin   proc: add seq_put...
716
717
718
719
720
721
  
  void seq_put_decimal_ull(struct seq_file *m, const char *delimiter,
  			 unsigned long long num)
  {
  	return seq_put_decimal_ull_width(m, delimiter, num, 0);
  }
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
722
  EXPORT_SYMBOL(seq_put_decimal_ull);
0e3dc0191   Andrei Vagin   procfs: add seq_p...
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
  /**
   * seq_put_hex_ll - put a number in hexadecimal notation
   * @m: seq_file identifying the buffer to which data should be written
   * @delimiter: a string which is printed before the number
   * @v: the number
   * @width: a minimum field width
   *
   * seq_put_hex_ll(m, "", v, 8) is equal to seq_printf(m, "%08llx", v)
   *
   * This routine is very quick when you show lots of numbers.
   * In usual cases, it will be better to use seq_printf(). It's easier to read.
   */
  void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
  				unsigned long long v, unsigned int width)
  {
  	unsigned int len;
  	int i;
  
  	if (delimiter && delimiter[0]) {
  		if (delimiter[1] == 0)
  			seq_putc(m, delimiter[0]);
  		else
  			seq_puts(m, delimiter);
  	}
  
  	/* If x is 0, the result of __builtin_clzll is undefined */
  	if (v == 0)
  		len = 1;
  	else
  		len = (sizeof(v) * 8 - __builtin_clzll(v) + 3) / 4;
  
  	if (len < width)
  		len = width;
  
  	if (m->count + len > m->size) {
  		seq_set_overflow(m);
  		return;
  	}
  
  	for (i = len - 1; i >= 0; i--) {
  		m->buf[m->count + i] = hex_asc[0xf & v];
  		v = v >> 4;
  	}
  	m->count += len;
  }
75ba1d07f   Joe Perches   seq/proc: modify ...
768
  void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
bda7bad62   KAMEZAWA Hiroyuki   procfs: speed up ...
769
  {
75ba1d07f   Joe Perches   seq/proc: modify ...
770
771
772
773
  	int len;
  
  	if (m->count + 3 >= m->size) /* we'll write 2 bytes at least */
  		goto overflow;
48dffbf82   Andrei Vagin   proc: optimize si...
774
775
776
777
778
779
  	if (delimiter && delimiter[0]) {
  		if (delimiter[1] == 0)
  			seq_putc(m, delimiter[0]);
  		else
  			seq_puts(m, delimiter);
  	}
75ba1d07f   Joe Perches   seq/proc: modify ...
780
781
782
  
  	if (m->count + 2 >= m->size)
  		goto overflow;
bda7bad62   KAMEZAWA Hiroyuki   procfs: speed up ...
783
  	if (num < 0) {
75ba1d07f   Joe Perches   seq/proc: modify ...
784
  		m->buf[m->count++] = '-';
bda7bad62   KAMEZAWA Hiroyuki   procfs: speed up ...
785
  		num = -num;
bda7bad62   KAMEZAWA Hiroyuki   procfs: speed up ...
786
  	}
75ba1d07f   Joe Perches   seq/proc: modify ...
787
788
789
790
791
  
  	if (num < 10) {
  		m->buf[m->count++] = num + '0';
  		return;
  	}
d1be35cb6   Andrei Vagin   proc: add seq_put...
792
  	len = num_to_str(m->buf + m->count, m->size - m->count, num, 0);
75ba1d07f   Joe Perches   seq/proc: modify ...
793
794
795
796
797
798
799
800
  	if (!len)
  		goto overflow;
  
  	m->count += len;
  	return;
  
  overflow:
  	seq_set_overflow(m);
bda7bad62   KAMEZAWA Hiroyuki   procfs: speed up ...
801
802
  }
  EXPORT_SYMBOL(seq_put_decimal_ll);
0b923606e   Peter Oberparleiter   seq_file: add fun...
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
  /**
   * seq_write - write arbitrary data to buffer
   * @seq: seq_file identifying the buffer to which data should be written
   * @data: data address
   * @len: number of bytes
   *
   * Return 0 on success, non-zero otherwise.
   */
  int seq_write(struct seq_file *seq, const void *data, size_t len)
  {
  	if (seq->count + len < seq->size) {
  		memcpy(seq->buf + seq->count, data, len);
  		seq->count += len;
  		return 0;
  	}
e075f5915   KAMEZAWA Hiroyuki   seq_file: add seq...
818
  	seq_set_overflow(seq);
0b923606e   Peter Oberparleiter   seq_file: add fun...
819
820
821
  	return -1;
  }
  EXPORT_SYMBOL(seq_write);
839cc2a94   Tetsuo Handa   seq_file: introdu...
822
823
824
825
826
827
828
829
  /**
   * seq_pad - write padding spaces to buffer
   * @m: seq_file identifying the buffer to which data should be written
   * @c: the byte to append after padding if non-zero
   */
  void seq_pad(struct seq_file *m, char c)
  {
  	int size = m->pad_until - m->count;
8cfa67b4d   Andrei Vagin   procfs: optimize ...
830
831
832
833
834
835
836
837
  	if (size > 0) {
  		if (size + m->count > m->size) {
  			seq_set_overflow(m);
  			return;
  		}
  		memset(m->buf + m->count, ' ', size);
  		m->count += size;
  	}
839cc2a94   Tetsuo Handa   seq_file: introdu...
838
839
840
841
  	if (c)
  		seq_putc(m, c);
  }
  EXPORT_SYMBOL(seq_pad);
37607102c   Andy Shevchenko   seq_file: provide...
842
843
844
845
846
847
848
  /* A complete analogue of print_hex_dump() */
  void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
  		  int rowsize, int groupsize, const void *buf, size_t len,
  		  bool ascii)
  {
  	const u8 *ptr = buf;
  	int i, linelen, remaining = len;
8b91a318e   Andy Shevchenko   fs/seq_file: use ...
849
850
  	char *buffer;
  	size_t size;
37607102c   Andy Shevchenko   seq_file: provide...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
  	int ret;
  
  	if (rowsize != 16 && rowsize != 32)
  		rowsize = 16;
  
  	for (i = 0; i < len && !seq_has_overflowed(m); i += rowsize) {
  		linelen = min(remaining, rowsize);
  		remaining -= rowsize;
  
  		switch (prefix_type) {
  		case DUMP_PREFIX_ADDRESS:
  			seq_printf(m, "%s%p: ", prefix_str, ptr + i);
  			break;
  		case DUMP_PREFIX_OFFSET:
  			seq_printf(m, "%s%.8x: ", prefix_str, i);
  			break;
  		default:
  			seq_printf(m, "%s", prefix_str);
  			break;
  		}
8b91a318e   Andy Shevchenko   fs/seq_file: use ...
871
  		size = seq_get_buf(m, &buffer);
37607102c   Andy Shevchenko   seq_file: provide...
872
  		ret = hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
8b91a318e   Andy Shevchenko   fs/seq_file: use ...
873
874
875
876
877
  					 buffer, size, ascii);
  		seq_commit(m, ret < size ? ret : -1);
  
  		seq_putc(m, '
  ');
37607102c   Andy Shevchenko   seq_file: provide...
878
879
880
  	}
  }
  EXPORT_SYMBOL(seq_hex_dump);
bcf67e162   Pavel Emelianov   Make common helpe...
881
882
883
884
885
886
887
888
889
890
  struct list_head *seq_list_start(struct list_head *head, loff_t pos)
  {
  	struct list_head *lh;
  
  	list_for_each(lh, head)
  		if (pos-- == 0)
  			return lh;
  
  	return NULL;
  }
bcf67e162   Pavel Emelianov   Make common helpe...
891
892
893
894
895
896
897
898
899
  EXPORT_SYMBOL(seq_list_start);
  
  struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
  {
  	if (!pos)
  		return head;
  
  	return seq_list_start(head, pos - 1);
  }
bcf67e162   Pavel Emelianov   Make common helpe...
900
901
902
903
904
905
906
907
908
909
  EXPORT_SYMBOL(seq_list_start_head);
  
  struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
  {
  	struct list_head *lh;
  
  	lh = ((struct list_head *)v)->next;
  	++*ppos;
  	return lh == head ? NULL : lh;
  }
bcf67e162   Pavel Emelianov   Make common helpe...
910
  EXPORT_SYMBOL(seq_list_next);
66655de6d   Li Zefan   seq_file: Add hel...
911

8371666ef   David Howells   rxrpc: Fix lockin...
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  struct list_head *seq_list_start_rcu(struct list_head *head, loff_t pos)
  {
  	struct list_head *lh;
  
  	list_for_each_rcu(lh, head)
  		if (pos-- == 0)
  			return lh;
  
  	return NULL;
  }
  EXPORT_SYMBOL(seq_list_start_rcu);
  
  struct list_head *seq_list_start_head_rcu(struct list_head *head, loff_t pos)
  {
  	if (!pos)
  		return head;
  
  	return seq_list_start_rcu(head, pos - 1);
  }
  EXPORT_SYMBOL(seq_list_start_head_rcu);
  
  struct list_head *seq_list_next_rcu(void *v, struct list_head *head,
  				    loff_t *ppos)
  {
  	struct list_head *lh;
  
  	lh = list_next_rcu((struct list_head *)v);
  	++*ppos;
  	return lh == head ? NULL : lh;
  }
  EXPORT_SYMBOL(seq_list_next_rcu);
66655de6d   Li Zefan   seq_file: Add hel...
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
  /**
   * seq_hlist_start - start an iteration of a hlist
   * @head: the head of the hlist
   * @pos:  the start position of the sequence
   *
   * Called at seq_file->op->start().
   */
  struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
  {
  	struct hlist_node *node;
  
  	hlist_for_each(node, head)
  		if (pos-- == 0)
  			return node;
  	return NULL;
  }
  EXPORT_SYMBOL(seq_hlist_start);
  
  /**
   * seq_hlist_start_head - start an iteration of a hlist
   * @head: the head of the hlist
   * @pos:  the start position of the sequence
   *
   * Called at seq_file->op->start(). Call this function if you want to
   * print a header at the top of the output.
   */
  struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
  {
  	if (!pos)
  		return SEQ_START_TOKEN;
  
  	return seq_hlist_start(head, pos - 1);
  }
  EXPORT_SYMBOL(seq_hlist_start_head);
  
  /**
   * seq_hlist_next - move to the next position of the hlist
   * @v:    the current iterator
   * @head: the head of the hlist
138860b95   Randy Dunlap   seq_file: fix new...
982
   * @ppos: the current position
66655de6d   Li Zefan   seq_file: Add hel...
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
   *
   * Called at seq_file->op->next().
   */
  struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
  				  loff_t *ppos)
  {
  	struct hlist_node *node = v;
  
  	++*ppos;
  	if (v == SEQ_START_TOKEN)
  		return head->first;
  	else
  		return node->next;
  }
  EXPORT_SYMBOL(seq_hlist_next);
1cc523271   stephen hemminger   seq_file: add RCU...
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  
  /**
   * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
   * @head: the head of the hlist
   * @pos:  the start position of the sequence
   *
   * Called at seq_file->op->start().
   *
   * This list-traversal primitive may safely run concurrently with
   * the _rcu list-mutation primitives such as hlist_add_head_rcu()
   * as long as the traversal is guarded by rcu_read_lock().
   */
  struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
  				       loff_t pos)
  {
  	struct hlist_node *node;
  
  	__hlist_for_each_rcu(node, head)
  		if (pos-- == 0)
  			return node;
  	return NULL;
  }
  EXPORT_SYMBOL(seq_hlist_start_rcu);
  
  /**
   * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
   * @head: the head of the hlist
   * @pos:  the start position of the sequence
   *
   * Called at seq_file->op->start(). Call this function if you want to
   * print a header at the top of the output.
   *
   * This list-traversal primitive may safely run concurrently with
   * the _rcu list-mutation primitives such as hlist_add_head_rcu()
   * as long as the traversal is guarded by rcu_read_lock().
   */
  struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
  					    loff_t pos)
  {
  	if (!pos)
  		return SEQ_START_TOKEN;
  
  	return seq_hlist_start_rcu(head, pos - 1);
  }
  EXPORT_SYMBOL(seq_hlist_start_head_rcu);
  
  /**
   * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
   * @v:    the current iterator
   * @head: the head of the hlist
138860b95   Randy Dunlap   seq_file: fix new...
1048
   * @ppos: the current position
1cc523271   stephen hemminger   seq_file: add RCU...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
   *
   * Called at seq_file->op->next().
   *
   * This list-traversal primitive may safely run concurrently with
   * the _rcu list-mutation primitives such as hlist_add_head_rcu()
   * as long as the traversal is guarded by rcu_read_lock().
   */
  struct hlist_node *seq_hlist_next_rcu(void *v,
  				      struct hlist_head *head,
  				      loff_t *ppos)
  {
  	struct hlist_node *node = v;
  
  	++*ppos;
  	if (v == SEQ_START_TOKEN)
  		return rcu_dereference(head->first);
  	else
  		return rcu_dereference(node->next);
  }
  EXPORT_SYMBOL(seq_hlist_next_rcu);
0bc77381c   Jeff Layton   seq_file: add seq...
1069
1070
  
  /**
961f3c898   Mauro Carvalho Chehab   fs: fix kernel-do...
1071
   * seq_hlist_start_percpu - start an iteration of a percpu hlist array
0bc77381c   Jeff Layton   seq_file: add seq...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
   * @head: pointer to percpu array of struct hlist_heads
   * @cpu:  pointer to cpu "cursor"
   * @pos:  start position of sequence
   *
   * Called at seq_file->op->start().
   */
  struct hlist_node *
  seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
  {
  	struct hlist_node *node;
  
  	for_each_possible_cpu(*cpu) {
  		hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
  			if (pos-- == 0)
  				return node;
  		}
  	}
  	return NULL;
  }
  EXPORT_SYMBOL(seq_hlist_start_percpu);
  
  /**
   * seq_hlist_next_percpu - move to the next position of the percpu hlist array
   * @v:    pointer to current hlist_node
   * @head: pointer to percpu array of struct hlist_heads
   * @cpu:  pointer to cpu "cursor"
   * @pos:  start position of sequence
   *
   * Called at seq_file->op->next().
   */
  struct hlist_node *
  seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
  			int *cpu, loff_t *pos)
  {
  	struct hlist_node *node = v;
  
  	++*pos;
  
  	if (node->next)
  		return node->next;
  
  	for (*cpu = cpumask_next(*cpu, cpu_possible_mask); *cpu < nr_cpu_ids;
  	     *cpu = cpumask_next(*cpu, cpu_possible_mask)) {
  		struct hlist_head *bucket = per_cpu_ptr(head, *cpu);
  
  		if (!hlist_empty(bucket))
  			return bucket->first;
  	}
  	return NULL;
  }
  EXPORT_SYMBOL(seq_hlist_next_percpu);
096523203   Alexey Dobriyan   seq_file: allocat...
1123
1124
1125
  
  void __init seq_file_init(void)
  {
d64d01a15   Alexey Dobriyan   seq_file: account...
1126
  	seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT|SLAB_PANIC);
096523203   Alexey Dobriyan   seq_file: allocat...
1127
  }