LCOV - code coverage report
Current view: top level - fs - seq_file.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 283 490 57.8 %
Date: 2021-04-22 12:43:58 Functions: 28 45 62.2 %

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

Generated by: LCOV version 1.14