0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #include <linux/cache.h>
0012 #include <linux/fs.h>
0013 #include <linux/export.h>
0014 #include <linux/seq_file.h>
0015 #include <linux/vmalloc.h>
0016 #include <linux/slab.h>
0017 #include <linux/cred.h>
0018 #include <linux/mm.h>
0019 #include <linux/printk.h>
0020 #include <linux/string_helpers.h>
0021 #include <linux/uio.h>
0022
0023 #include <linux/uaccess.h>
0024 #include <asm/page.h>
0025
0026 static struct kmem_cache *seq_file_cache __ro_after_init;
0027
0028 static void seq_set_overflow(struct seq_file *m)
0029 {
0030 m->count = m->size;
0031 }
0032
0033 static void *seq_buf_alloc(unsigned long size)
0034 {
0035 if (unlikely(size > MAX_RW_COUNT))
0036 return NULL;
0037
0038 return kvmalloc(size, GFP_KERNEL_ACCOUNT);
0039 }
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 int seq_open(struct file *file, const struct seq_operations *op)
0058 {
0059 struct seq_file *p;
0060
0061 WARN_ON(file->private_data);
0062
0063 p = kmem_cache_zalloc(seq_file_cache, GFP_KERNEL);
0064 if (!p)
0065 return -ENOMEM;
0066
0067 file->private_data = p;
0068
0069 mutex_init(&p->lock);
0070 p->op = op;
0071
0072
0073
0074 p->file = file;
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 file->f_mode &= ~FMODE_PWRITE;
0086 return 0;
0087 }
0088 EXPORT_SYMBOL(seq_open);
0089
0090 static int traverse(struct seq_file *m, loff_t offset)
0091 {
0092 loff_t pos = 0;
0093 int error = 0;
0094 void *p;
0095
0096 m->index = 0;
0097 m->count = m->from = 0;
0098 if (!offset)
0099 return 0;
0100
0101 if (!m->buf) {
0102 m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
0103 if (!m->buf)
0104 return -ENOMEM;
0105 }
0106 p = m->op->start(m, &m->index);
0107 while (p) {
0108 error = PTR_ERR(p);
0109 if (IS_ERR(p))
0110 break;
0111 error = m->op->show(m, p);
0112 if (error < 0)
0113 break;
0114 if (unlikely(error)) {
0115 error = 0;
0116 m->count = 0;
0117 }
0118 if (seq_has_overflowed(m))
0119 goto Eoverflow;
0120 p = m->op->next(m, p, &m->index);
0121 if (pos + m->count > offset) {
0122 m->from = offset - pos;
0123 m->count -= m->from;
0124 break;
0125 }
0126 pos += m->count;
0127 m->count = 0;
0128 if (pos == offset)
0129 break;
0130 }
0131 m->op->stop(m, p);
0132 return error;
0133
0134 Eoverflow:
0135 m->op->stop(m, p);
0136 kvfree(m->buf);
0137 m->count = 0;
0138 m->buf = seq_buf_alloc(m->size <<= 1);
0139 return !m->buf ? -ENOMEM : -EAGAIN;
0140 }
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
0152 {
0153 struct iovec iov = { .iov_base = buf, .iov_len = size};
0154 struct kiocb kiocb;
0155 struct iov_iter iter;
0156 ssize_t ret;
0157
0158 init_sync_kiocb(&kiocb, file);
0159 iov_iter_init(&iter, READ, &iov, 1, size);
0160
0161 kiocb.ki_pos = *ppos;
0162 ret = seq_read_iter(&kiocb, &iter);
0163 *ppos = kiocb.ki_pos;
0164 return ret;
0165 }
0166 EXPORT_SYMBOL(seq_read);
0167
0168
0169
0170
0171 ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
0172 {
0173 struct seq_file *m = iocb->ki_filp->private_data;
0174 size_t copied = 0;
0175 size_t n;
0176 void *p;
0177 int err = 0;
0178
0179 if (!iov_iter_count(iter))
0180 return 0;
0181
0182 mutex_lock(&m->lock);
0183
0184
0185
0186
0187
0188 if (iocb->ki_pos == 0) {
0189 m->index = 0;
0190 m->count = 0;
0191 }
0192
0193
0194 if (unlikely(iocb->ki_pos != m->read_pos)) {
0195 while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
0196 ;
0197 if (err) {
0198
0199 m->read_pos = 0;
0200 m->index = 0;
0201 m->count = 0;
0202 goto Done;
0203 } else {
0204 m->read_pos = iocb->ki_pos;
0205 }
0206 }
0207
0208
0209 if (!m->buf) {
0210 m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
0211 if (!m->buf)
0212 goto Enomem;
0213 }
0214
0215 if (m->count) {
0216 n = copy_to_iter(m->buf + m->from, m->count, iter);
0217 m->count -= n;
0218 m->from += n;
0219 copied += n;
0220 if (m->count)
0221 goto Done;
0222 }
0223
0224 m->from = 0;
0225 p = m->op->start(m, &m->index);
0226 while (1) {
0227 err = PTR_ERR(p);
0228 if (!p || IS_ERR(p))
0229 break;
0230 err = m->op->show(m, p);
0231 if (err < 0)
0232 break;
0233 if (unlikely(err))
0234 m->count = 0;
0235 if (unlikely(!m->count)) {
0236 p = m->op->next(m, p, &m->index);
0237 continue;
0238 }
0239 if (!seq_has_overflowed(m))
0240 goto Fill;
0241
0242 m->op->stop(m, p);
0243 kvfree(m->buf);
0244 m->count = 0;
0245 m->buf = seq_buf_alloc(m->size <<= 1);
0246 if (!m->buf)
0247 goto Enomem;
0248 p = m->op->start(m, &m->index);
0249 }
0250
0251 m->op->stop(m, p);
0252 m->count = 0;
0253 goto Done;
0254 Fill:
0255
0256
0257
0258 while (1) {
0259 size_t offs = m->count;
0260 loff_t pos = m->index;
0261
0262 p = m->op->next(m, p, &m->index);
0263 if (pos == m->index) {
0264 pr_info_ratelimited("buggy .next function %ps did not update position index\n",
0265 m->op->next);
0266 m->index++;
0267 }
0268 if (!p || IS_ERR(p))
0269 break;
0270 if (m->count >= iov_iter_count(iter))
0271 break;
0272 err = m->op->show(m, p);
0273 if (err > 0) {
0274 m->count = offs;
0275 } else if (err || seq_has_overflowed(m)) {
0276 m->count = offs;
0277 break;
0278 }
0279 }
0280 m->op->stop(m, p);
0281 n = copy_to_iter(m->buf, m->count, iter);
0282 copied += n;
0283 m->count -= n;
0284 m->from = n;
0285 Done:
0286 if (unlikely(!copied)) {
0287 copied = m->count ? -EFAULT : err;
0288 } else {
0289 iocb->ki_pos += copied;
0290 m->read_pos += copied;
0291 }
0292 mutex_unlock(&m->lock);
0293 return copied;
0294 Enomem:
0295 err = -ENOMEM;
0296 goto Done;
0297 }
0298 EXPORT_SYMBOL(seq_read_iter);
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 loff_t seq_lseek(struct file *file, loff_t offset, int whence)
0309 {
0310 struct seq_file *m = file->private_data;
0311 loff_t retval = -EINVAL;
0312
0313 mutex_lock(&m->lock);
0314 switch (whence) {
0315 case SEEK_CUR:
0316 offset += file->f_pos;
0317 fallthrough;
0318 case SEEK_SET:
0319 if (offset < 0)
0320 break;
0321 retval = offset;
0322 if (offset != m->read_pos) {
0323 while ((retval = traverse(m, offset)) == -EAGAIN)
0324 ;
0325 if (retval) {
0326
0327 file->f_pos = 0;
0328 m->read_pos = 0;
0329 m->index = 0;
0330 m->count = 0;
0331 } else {
0332 m->read_pos = offset;
0333 retval = file->f_pos = offset;
0334 }
0335 } else {
0336 file->f_pos = offset;
0337 }
0338 }
0339 mutex_unlock(&m->lock);
0340 return retval;
0341 }
0342 EXPORT_SYMBOL(seq_lseek);
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 int seq_release(struct inode *inode, struct file *file)
0353 {
0354 struct seq_file *m = file->private_data;
0355 kvfree(m->buf);
0356 kmem_cache_free(seq_file_cache, m);
0357 return 0;
0358 }
0359 EXPORT_SYMBOL(seq_release);
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 void seq_escape_mem(struct seq_file *m, const char *src, size_t len,
0375 unsigned int flags, const char *esc)
0376 {
0377 char *buf;
0378 size_t size = seq_get_buf(m, &buf);
0379 int ret;
0380
0381 ret = string_escape_mem(src, len, buf, size, flags, esc);
0382 seq_commit(m, ret < size ? ret : -1);
0383 }
0384 EXPORT_SYMBOL(seq_escape_mem);
0385
0386 void seq_vprintf(struct seq_file *m, const char *f, va_list args)
0387 {
0388 int len;
0389
0390 if (m->count < m->size) {
0391 len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
0392 if (m->count + len < m->size) {
0393 m->count += len;
0394 return;
0395 }
0396 }
0397 seq_set_overflow(m);
0398 }
0399 EXPORT_SYMBOL(seq_vprintf);
0400
0401 void seq_printf(struct seq_file *m, const char *f, ...)
0402 {
0403 va_list args;
0404
0405 va_start(args, f);
0406 seq_vprintf(m, f, args);
0407 va_end(args);
0408 }
0409 EXPORT_SYMBOL(seq_printf);
0410
0411 #ifdef CONFIG_BINARY_PRINTF
0412 void seq_bprintf(struct seq_file *m, const char *f, const u32 *binary)
0413 {
0414 int len;
0415
0416 if (m->count < m->size) {
0417 len = bstr_printf(m->buf + m->count, m->size - m->count, f,
0418 binary);
0419 if (m->count + len < m->size) {
0420 m->count += len;
0421 return;
0422 }
0423 }
0424 seq_set_overflow(m);
0425 }
0426 EXPORT_SYMBOL(seq_bprintf);
0427 #endif
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 char *mangle_path(char *s, const char *p, const char *esc)
0441 {
0442 while (s <= p) {
0443 char c = *p++;
0444 if (!c) {
0445 return s;
0446 } else if (!strchr(esc, c)) {
0447 *s++ = c;
0448 } else if (s + 4 > p) {
0449 break;
0450 } else {
0451 *s++ = '\\';
0452 *s++ = '0' + ((c & 0300) >> 6);
0453 *s++ = '0' + ((c & 070) >> 3);
0454 *s++ = '0' + (c & 07);
0455 }
0456 }
0457 return NULL;
0458 }
0459 EXPORT_SYMBOL(mangle_path);
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 int seq_path(struct seq_file *m, const struct path *path, const char *esc)
0471 {
0472 char *buf;
0473 size_t size = seq_get_buf(m, &buf);
0474 int res = -1;
0475
0476 if (size) {
0477 char *p = d_path(path, buf, size);
0478 if (!IS_ERR(p)) {
0479 char *end = mangle_path(buf, p, esc);
0480 if (end)
0481 res = end - buf;
0482 }
0483 }
0484 seq_commit(m, res);
0485
0486 return res;
0487 }
0488 EXPORT_SYMBOL(seq_path);
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 int seq_file_path(struct seq_file *m, struct file *file, const char *esc)
0499 {
0500 return seq_path(m, &file->f_path, esc);
0501 }
0502 EXPORT_SYMBOL(seq_file_path);
0503
0504
0505
0506
0507 int seq_path_root(struct seq_file *m, const struct path *path,
0508 const struct path *root, const char *esc)
0509 {
0510 char *buf;
0511 size_t size = seq_get_buf(m, &buf);
0512 int res = -ENAMETOOLONG;
0513
0514 if (size) {
0515 char *p;
0516
0517 p = __d_path(path, root, buf, size);
0518 if (!p)
0519 return SEQ_SKIP;
0520 res = PTR_ERR(p);
0521 if (!IS_ERR(p)) {
0522 char *end = mangle_path(buf, p, esc);
0523 if (end)
0524 res = end - buf;
0525 else
0526 res = -ENAMETOOLONG;
0527 }
0528 }
0529 seq_commit(m, res);
0530
0531 return res < 0 && res != -ENAMETOOLONG ? res : 0;
0532 }
0533
0534
0535
0536
0537 int seq_dentry(struct seq_file *m, struct dentry *dentry, const char *esc)
0538 {
0539 char *buf;
0540 size_t size = seq_get_buf(m, &buf);
0541 int res = -1;
0542
0543 if (size) {
0544 char *p = dentry_path(dentry, buf, size);
0545 if (!IS_ERR(p)) {
0546 char *end = mangle_path(buf, p, esc);
0547 if (end)
0548 res = end - buf;
0549 }
0550 }
0551 seq_commit(m, res);
0552
0553 return res;
0554 }
0555 EXPORT_SYMBOL(seq_dentry);
0556
0557 void *single_start(struct seq_file *p, loff_t *pos)
0558 {
0559 return *pos ? NULL : SEQ_START_TOKEN;
0560 }
0561
0562 static void *single_next(struct seq_file *p, void *v, loff_t *pos)
0563 {
0564 ++*pos;
0565 return NULL;
0566 }
0567
0568 static void single_stop(struct seq_file *p, void *v)
0569 {
0570 }
0571
0572 int single_open(struct file *file, int (*show)(struct seq_file *, void *),
0573 void *data)
0574 {
0575 struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
0576 int res = -ENOMEM;
0577
0578 if (op) {
0579 op->start = single_start;
0580 op->next = single_next;
0581 op->stop = single_stop;
0582 op->show = show;
0583 res = seq_open(file, op);
0584 if (!res)
0585 ((struct seq_file *)file->private_data)->private = data;
0586 else
0587 kfree(op);
0588 }
0589 return res;
0590 }
0591 EXPORT_SYMBOL(single_open);
0592
0593 int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
0594 void *data, size_t size)
0595 {
0596 char *buf = seq_buf_alloc(size);
0597 int ret;
0598 if (!buf)
0599 return -ENOMEM;
0600 ret = single_open(file, show, data);
0601 if (ret) {
0602 kvfree(buf);
0603 return ret;
0604 }
0605 ((struct seq_file *)file->private_data)->buf = buf;
0606 ((struct seq_file *)file->private_data)->size = size;
0607 return 0;
0608 }
0609 EXPORT_SYMBOL(single_open_size);
0610
0611 int single_release(struct inode *inode, struct file *file)
0612 {
0613 const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
0614 int res = seq_release(inode, file);
0615 kfree(op);
0616 return res;
0617 }
0618 EXPORT_SYMBOL(single_release);
0619
0620 int seq_release_private(struct inode *inode, struct file *file)
0621 {
0622 struct seq_file *seq = file->private_data;
0623
0624 kfree(seq->private);
0625 seq->private = NULL;
0626 return seq_release(inode, file);
0627 }
0628 EXPORT_SYMBOL(seq_release_private);
0629
0630 void *__seq_open_private(struct file *f, const struct seq_operations *ops,
0631 int psize)
0632 {
0633 int rc;
0634 void *private;
0635 struct seq_file *seq;
0636
0637 private = kzalloc(psize, GFP_KERNEL_ACCOUNT);
0638 if (private == NULL)
0639 goto out;
0640
0641 rc = seq_open(f, ops);
0642 if (rc < 0)
0643 goto out_free;
0644
0645 seq = f->private_data;
0646 seq->private = private;
0647 return private;
0648
0649 out_free:
0650 kfree(private);
0651 out:
0652 return NULL;
0653 }
0654 EXPORT_SYMBOL(__seq_open_private);
0655
0656 int seq_open_private(struct file *filp, const struct seq_operations *ops,
0657 int psize)
0658 {
0659 return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
0660 }
0661 EXPORT_SYMBOL(seq_open_private);
0662
0663 void seq_putc(struct seq_file *m, char c)
0664 {
0665 if (m->count >= m->size)
0666 return;
0667
0668 m->buf[m->count++] = c;
0669 }
0670 EXPORT_SYMBOL(seq_putc);
0671
0672 void seq_puts(struct seq_file *m, const char *s)
0673 {
0674 int len = strlen(s);
0675
0676 if (m->count + len >= m->size) {
0677 seq_set_overflow(m);
0678 return;
0679 }
0680 memcpy(m->buf + m->count, s, len);
0681 m->count += len;
0682 }
0683 EXPORT_SYMBOL(seq_puts);
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
0699 unsigned long long num, unsigned int width)
0700 {
0701 int len;
0702
0703 if (m->count + 2 >= m->size)
0704 goto overflow;
0705
0706 if (delimiter && delimiter[0]) {
0707 if (delimiter[1] == 0)
0708 seq_putc(m, delimiter[0]);
0709 else
0710 seq_puts(m, delimiter);
0711 }
0712
0713 if (!width)
0714 width = 1;
0715
0716 if (m->count + width >= m->size)
0717 goto overflow;
0718
0719 len = num_to_str(m->buf + m->count, m->size - m->count, num, width);
0720 if (!len)
0721 goto overflow;
0722
0723 m->count += len;
0724 return;
0725
0726 overflow:
0727 seq_set_overflow(m);
0728 }
0729
0730 void seq_put_decimal_ull(struct seq_file *m, const char *delimiter,
0731 unsigned long long num)
0732 {
0733 return seq_put_decimal_ull_width(m, delimiter, num, 0);
0734 }
0735 EXPORT_SYMBOL(seq_put_decimal_ull);
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749 void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
0750 unsigned long long v, unsigned int width)
0751 {
0752 unsigned int len;
0753 int i;
0754
0755 if (delimiter && delimiter[0]) {
0756 if (delimiter[1] == 0)
0757 seq_putc(m, delimiter[0]);
0758 else
0759 seq_puts(m, delimiter);
0760 }
0761
0762
0763 if (v == 0)
0764 len = 1;
0765 else
0766 len = (sizeof(v) * 8 - __builtin_clzll(v) + 3) / 4;
0767
0768 if (len < width)
0769 len = width;
0770
0771 if (m->count + len > m->size) {
0772 seq_set_overflow(m);
0773 return;
0774 }
0775
0776 for (i = len - 1; i >= 0; i--) {
0777 m->buf[m->count + i] = hex_asc[0xf & v];
0778 v = v >> 4;
0779 }
0780 m->count += len;
0781 }
0782
0783 void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
0784 {
0785 int len;
0786
0787 if (m->count + 3 >= m->size)
0788 goto overflow;
0789
0790 if (delimiter && delimiter[0]) {
0791 if (delimiter[1] == 0)
0792 seq_putc(m, delimiter[0]);
0793 else
0794 seq_puts(m, delimiter);
0795 }
0796
0797 if (m->count + 2 >= m->size)
0798 goto overflow;
0799
0800 if (num < 0) {
0801 m->buf[m->count++] = '-';
0802 num = -num;
0803 }
0804
0805 if (num < 10) {
0806 m->buf[m->count++] = num + '0';
0807 return;
0808 }
0809
0810 len = num_to_str(m->buf + m->count, m->size - m->count, num, 0);
0811 if (!len)
0812 goto overflow;
0813
0814 m->count += len;
0815 return;
0816
0817 overflow:
0818 seq_set_overflow(m);
0819 }
0820 EXPORT_SYMBOL(seq_put_decimal_ll);
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830 int seq_write(struct seq_file *seq, const void *data, size_t len)
0831 {
0832 if (seq->count + len < seq->size) {
0833 memcpy(seq->buf + seq->count, data, len);
0834 seq->count += len;
0835 return 0;
0836 }
0837 seq_set_overflow(seq);
0838 return -1;
0839 }
0840 EXPORT_SYMBOL(seq_write);
0841
0842
0843
0844
0845
0846
0847 void seq_pad(struct seq_file *m, char c)
0848 {
0849 int size = m->pad_until - m->count;
0850 if (size > 0) {
0851 if (size + m->count > m->size) {
0852 seq_set_overflow(m);
0853 return;
0854 }
0855 memset(m->buf + m->count, ' ', size);
0856 m->count += size;
0857 }
0858 if (c)
0859 seq_putc(m, c);
0860 }
0861 EXPORT_SYMBOL(seq_pad);
0862
0863
0864 void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
0865 int rowsize, int groupsize, const void *buf, size_t len,
0866 bool ascii)
0867 {
0868 const u8 *ptr = buf;
0869 int i, linelen, remaining = len;
0870 char *buffer;
0871 size_t size;
0872 int ret;
0873
0874 if (rowsize != 16 && rowsize != 32)
0875 rowsize = 16;
0876
0877 for (i = 0; i < len && !seq_has_overflowed(m); i += rowsize) {
0878 linelen = min(remaining, rowsize);
0879 remaining -= rowsize;
0880
0881 switch (prefix_type) {
0882 case DUMP_PREFIX_ADDRESS:
0883 seq_printf(m, "%s%p: ", prefix_str, ptr + i);
0884 break;
0885 case DUMP_PREFIX_OFFSET:
0886 seq_printf(m, "%s%.8x: ", prefix_str, i);
0887 break;
0888 default:
0889 seq_printf(m, "%s", prefix_str);
0890 break;
0891 }
0892
0893 size = seq_get_buf(m, &buffer);
0894 ret = hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
0895 buffer, size, ascii);
0896 seq_commit(m, ret < size ? ret : -1);
0897
0898 seq_putc(m, '\n');
0899 }
0900 }
0901 EXPORT_SYMBOL(seq_hex_dump);
0902
0903 struct list_head *seq_list_start(struct list_head *head, loff_t pos)
0904 {
0905 struct list_head *lh;
0906
0907 list_for_each(lh, head)
0908 if (pos-- == 0)
0909 return lh;
0910
0911 return NULL;
0912 }
0913 EXPORT_SYMBOL(seq_list_start);
0914
0915 struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
0916 {
0917 if (!pos)
0918 return head;
0919
0920 return seq_list_start(head, pos - 1);
0921 }
0922 EXPORT_SYMBOL(seq_list_start_head);
0923
0924 struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
0925 {
0926 struct list_head *lh;
0927
0928 lh = ((struct list_head *)v)->next;
0929 ++*ppos;
0930 return lh == head ? NULL : lh;
0931 }
0932 EXPORT_SYMBOL(seq_list_next);
0933
0934 struct list_head *seq_list_start_rcu(struct list_head *head, loff_t pos)
0935 {
0936 struct list_head *lh;
0937
0938 list_for_each_rcu(lh, head)
0939 if (pos-- == 0)
0940 return lh;
0941
0942 return NULL;
0943 }
0944 EXPORT_SYMBOL(seq_list_start_rcu);
0945
0946 struct list_head *seq_list_start_head_rcu(struct list_head *head, loff_t pos)
0947 {
0948 if (!pos)
0949 return head;
0950
0951 return seq_list_start_rcu(head, pos - 1);
0952 }
0953 EXPORT_SYMBOL(seq_list_start_head_rcu);
0954
0955 struct list_head *seq_list_next_rcu(void *v, struct list_head *head,
0956 loff_t *ppos)
0957 {
0958 struct list_head *lh;
0959
0960 lh = list_next_rcu((struct list_head *)v);
0961 ++*ppos;
0962 return lh == head ? NULL : lh;
0963 }
0964 EXPORT_SYMBOL(seq_list_next_rcu);
0965
0966
0967
0968
0969
0970
0971
0972
0973 struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
0974 {
0975 struct hlist_node *node;
0976
0977 hlist_for_each(node, head)
0978 if (pos-- == 0)
0979 return node;
0980 return NULL;
0981 }
0982 EXPORT_SYMBOL(seq_hlist_start);
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992 struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
0993 {
0994 if (!pos)
0995 return SEQ_START_TOKEN;
0996
0997 return seq_hlist_start(head, pos - 1);
0998 }
0999 EXPORT_SYMBOL(seq_hlist_start_head);
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
1010 loff_t *ppos)
1011 {
1012 struct hlist_node *node = v;
1013
1014 ++*ppos;
1015 if (v == SEQ_START_TOKEN)
1016 return head->first;
1017 else
1018 return node->next;
1019 }
1020 EXPORT_SYMBOL(seq_hlist_next);
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
1034 loff_t pos)
1035 {
1036 struct hlist_node *node;
1037
1038 __hlist_for_each_rcu(node, head)
1039 if (pos-- == 0)
1040 return node;
1041 return NULL;
1042 }
1043 EXPORT_SYMBOL(seq_hlist_start_rcu);
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
1058 loff_t pos)
1059 {
1060 if (!pos)
1061 return SEQ_START_TOKEN;
1062
1063 return seq_hlist_start_rcu(head, pos - 1);
1064 }
1065 EXPORT_SYMBOL(seq_hlist_start_head_rcu);
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079 struct hlist_node *seq_hlist_next_rcu(void *v,
1080 struct hlist_head *head,
1081 loff_t *ppos)
1082 {
1083 struct hlist_node *node = v;
1084
1085 ++*ppos;
1086 if (v == SEQ_START_TOKEN)
1087 return rcu_dereference(head->first);
1088 else
1089 return rcu_dereference(node->next);
1090 }
1091 EXPORT_SYMBOL(seq_hlist_next_rcu);
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 struct hlist_node *
1102 seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
1103 {
1104 struct hlist_node *node;
1105
1106 for_each_possible_cpu(*cpu) {
1107 hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
1108 if (pos-- == 0)
1109 return node;
1110 }
1111 }
1112 return NULL;
1113 }
1114 EXPORT_SYMBOL(seq_hlist_start_percpu);
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125 struct hlist_node *
1126 seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
1127 int *cpu, loff_t *pos)
1128 {
1129 struct hlist_node *node = v;
1130
1131 ++*pos;
1132
1133 if (node->next)
1134 return node->next;
1135
1136 for (*cpu = cpumask_next(*cpu, cpu_possible_mask); *cpu < nr_cpu_ids;
1137 *cpu = cpumask_next(*cpu, cpu_possible_mask)) {
1138 struct hlist_head *bucket = per_cpu_ptr(head, *cpu);
1139
1140 if (!hlist_empty(bucket))
1141 return bucket->first;
1142 }
1143 return NULL;
1144 }
1145 EXPORT_SYMBOL(seq_hlist_next_percpu);
1146
1147 void __init seq_file_init(void)
1148 {
1149 seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT|SLAB_PANIC);
1150 }