LCOV - code coverage report
Current view: top level - fs - seq_file.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 349 499 69.9 %
Date: 2023-07-31 20:08:12 Functions: 36 49 73.5 %

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

Generated by: LCOV version 1.14