LCOV - code coverage report
Current view: top level - fs - seq_file.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 422 0.7 %
Date: 2023-07-19 18:55:55 Functions: 1 47 2.1 %

          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           0 :         m->count = m->size;
      31             : }
      32             : 
      33             : static void *seq_buf_alloc(unsigned long size)
      34             : {
      35           0 :         if (unlikely(size > MAX_RW_COUNT))
      36             :                 return NULL;
      37             : 
      38           0 :         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           0 : int seq_open(struct file *file, const struct seq_operations *op)
      58             : {
      59             :         struct seq_file *p;
      60             : 
      61           0 :         WARN_ON(file->private_data);
      62             : 
      63           0 :         p = kmem_cache_zalloc(seq_file_cache, GFP_KERNEL);
      64           0 :         if (!p)
      65             :                 return -ENOMEM;
      66             : 
      67           0 :         file->private_data = p;
      68             : 
      69           0 :         mutex_init(&p->lock);
      70           0 :         p->op = op;
      71             : 
      72             :         // No refcounting: the lifetime of 'p' is constrained
      73             :         // to the lifetime of the file.
      74           0 :         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           0 :         file->f_mode &= ~FMODE_PWRITE;
      86           0 :         return 0;
      87             : }
      88             : EXPORT_SYMBOL(seq_open);
      89             : 
      90           0 : static int traverse(struct seq_file *m, loff_t offset)
      91             : {
      92           0 :         loff_t pos = 0;
      93           0 :         int error = 0;
      94             :         void *p;
      95             : 
      96           0 :         m->index = 0;
      97           0 :         m->count = m->from = 0;
      98           0 :         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             :                         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           0 : ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
     152             : {
     153           0 :         struct iovec iov = { .iov_base = buf, .iov_len = size};
     154             :         struct kiocb kiocb;
     155             :         struct iov_iter iter;
     156             :         ssize_t ret;
     157             : 
     158           0 :         init_sync_kiocb(&kiocb, file);
     159           0 :         iov_iter_init(&iter, ITER_DEST, &iov, 1, size);
     160             : 
     161           0 :         kiocb.ki_pos = *ppos;
     162           0 :         ret = seq_read_iter(&kiocb, &iter);
     163           0 :         *ppos = kiocb.ki_pos;
     164           0 :         return ret;
     165             : }
     166             : EXPORT_SYMBOL(seq_read);
     167             : 
     168             : /*
     169             :  * Ready-made ->f_op->read_iter()
     170             :  */
     171           0 : ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
     172             : {
     173           0 :         struct seq_file *m = iocb->ki_filp->private_data;
     174           0 :         size_t copied = 0;
     175             :         size_t n;
     176             :         void *p;
     177           0 :         int err = 0;
     178             : 
     179           0 :         if (!iov_iter_count(iter))
     180             :                 return 0;
     181             : 
     182           0 :         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           0 :         if (iocb->ki_pos == 0) {
     189           0 :                 m->index = 0;
     190           0 :                 m->count = 0;
     191             :         }
     192             : 
     193             :         /* Don't assume ki_pos is where we left it */
     194           0 :         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           0 :         if (!m->buf) {
     210           0 :                 m->buf = seq_buf_alloc(m->size = PAGE_SIZE);
     211           0 :                 if (!m->buf)
     212             :                         goto Enomem;
     213             :         }
     214             :         // something left in the buffer - copy it out first
     215           0 :         if (m->count) {
     216           0 :                 n = copy_to_iter(m->buf + m->from, m->count, iter);
     217           0 :                 m->count -= n;
     218           0 :                 m->from += n;
     219           0 :                 copied += n;
     220           0 :                 if (m->count)        // hadn't managed to copy everything
     221             :                         goto Done;
     222             :         }
     223             :         // get a non-empty record in the buffer
     224           0 :         m->from = 0;
     225           0 :         p = m->op->start(m, &m->index);
     226             :         while (1) {
     227           0 :                 err = PTR_ERR(p);
     228           0 :                 if (!p || IS_ERR(p))    // EOF or an error
     229             :                         break;
     230           0 :                 err = m->op->show(m, p);
     231           0 :                 if (err < 0)         // hard error
     232             :                         break;
     233           0 :                 if (unlikely(err))      // ->show() says "skip it"
     234           0 :                         m->count = 0;
     235           0 :                 if (unlikely(!m->count)) { // empty record
     236           0 :                         p = m->op->next(m, p, &m->index);
     237           0 :                         continue;
     238             :                 }
     239           0 :                 if (!seq_has_overflowed(m)) // got it
     240             :                         goto Fill;
     241             :                 // need a bigger buffer
     242           0 :                 m->op->stop(m, p);
     243           0 :                 kvfree(m->buf);
     244           0 :                 m->count = 0;
     245           0 :                 m->buf = seq_buf_alloc(m->size <<= 1);
     246           0 :                 if (!m->buf)
     247             :                         goto Enomem;
     248           0 :                 p = m->op->start(m, &m->index);
     249             :         }
     250             :         // EOF or an error
     251           0 :         m->op->stop(m, p);
     252           0 :         m->count = 0;
     253           0 :         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             :         while (1) {
     259           0 :                 size_t offs = m->count;
     260           0 :                 loff_t pos = m->index;
     261             : 
     262           0 :                 p = m->op->next(m, p, &m->index);
     263           0 :                 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           0 :                 if (!p || IS_ERR(p))    // no next record for us
     269             :                         break;
     270           0 :                 if (m->count >= iov_iter_count(iter))
     271             :                         break;
     272           0 :                 err = m->op->show(m, p);
     273           0 :                 if (err > 0) {               // ->show() says "skip it"
     274           0 :                         m->count = offs;
     275           0 :                 } else if (err || seq_has_overflowed(m)) {
     276           0 :                         m->count = offs;
     277           0 :                         break;
     278             :                 }
     279             :         }
     280           0 :         m->op->stop(m, p);
     281           0 :         n = copy_to_iter(m->buf, m->count, iter);
     282           0 :         copied += n;
     283           0 :         m->count -= n;
     284           0 :         m->from = n;
     285             : Done:
     286           0 :         if (unlikely(!copied)) {
     287           0 :                 copied = m->count ? -EFAULT : err;
     288             :         } else {
     289           0 :                 iocb->ki_pos += copied;
     290           0 :                 m->read_pos += copied;
     291             :         }
     292           0 :         mutex_unlock(&m->lock);
     293           0 :         return copied;
     294             : Enomem:
     295             :         err = -ENOMEM;
     296             :         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           0 : loff_t seq_lseek(struct file *file, loff_t offset, int whence)
     309             : {
     310           0 :         struct seq_file *m = file->private_data;
     311           0 :         loff_t retval = -EINVAL;
     312             : 
     313           0 :         mutex_lock(&m->lock);
     314           0 :         switch (whence) {
     315             :         case SEEK_CUR:
     316           0 :                 offset += file->f_pos;
     317             :                 fallthrough;
     318             :         case SEEK_SET:
     319           0 :                 if (offset < 0)
     320             :                         break;
     321           0 :                 retval = offset;
     322           0 :                 if (offset != m->read_pos) {
     323           0 :                         while ((retval = traverse(m, offset)) == -EAGAIN)
     324             :                                 ;
     325           0 :                         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           0 :                                 m->read_pos = offset;
     333           0 :                                 retval = file->f_pos = offset;
     334             :                         }
     335             :                 } else {
     336           0 :                         file->f_pos = offset;
     337             :                 }
     338             :         }
     339           0 :         mutex_unlock(&m->lock);
     340           0 :         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           0 : int seq_release(struct inode *inode, struct file *file)
     353             : {
     354           0 :         struct seq_file *m = file->private_data;
     355           0 :         kvfree(m->buf);
     356           0 :         kmem_cache_free(seq_file_cache, m);
     357           0 :         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           0 : void seq_escape_mem(struct seq_file *m, const char *src, size_t len,
     375             :                     unsigned int flags, const char *esc)
     376             : {
     377             :         char *buf;
     378           0 :         size_t size = seq_get_buf(m, &buf);
     379             :         int ret;
     380             : 
     381           0 :         ret = string_escape_mem(src, len, buf, size, flags, esc);
     382           0 :         seq_commit(m, ret < size ? ret : -1);
     383           0 : }
     384             : EXPORT_SYMBOL(seq_escape_mem);
     385             : 
     386           0 : void seq_vprintf(struct seq_file *m, const char *f, va_list args)
     387             : {
     388             :         int len;
     389             : 
     390           0 :         if (m->count < m->size) {
     391           0 :                 len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
     392           0 :                 if (m->count + len < m->size) {
     393           0 :                         m->count += len;
     394           0 :                         return;
     395             :                 }
     396             :         }
     397           0 :         seq_set_overflow(m);
     398             : }
     399             : EXPORT_SYMBOL(seq_vprintf);
     400             : 
     401           0 : void seq_printf(struct seq_file *m, const char *f, ...)
     402             : {
     403             :         va_list args;
     404             : 
     405           0 :         va_start(args, f);
     406           0 :         seq_vprintf(m, f, args);
     407           0 :         va_end(args);
     408           0 : }
     409             : EXPORT_SYMBOL(seq_printf);
     410             : 
     411             : #ifdef CONFIG_BINARY_PRINTF
     412             : void seq_bprintf(struct seq_file *m, const char *f, const u32 *binary)
     413             : {
     414             :         int len;
     415             : 
     416             :         if (m->count < m->size) {
     417             :                 len = bstr_printf(m->buf + m->count, m->size - m->count, f,
     418             :                                   binary);
     419             :                 if (m->count + len < m->size) {
     420             :                         m->count += len;
     421             :                         return;
     422             :                 }
     423             :         }
     424             :         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           0 : char *mangle_path(char *s, const char *p, const char *esc)
     441             : {
     442           0 :         while (s <= p) {
     443           0 :                 char c = *p++;
     444           0 :                 if (!c) {
     445             :                         return s;
     446           0 :                 } else if (!strchr(esc, c)) {
     447           0 :                         *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           0 : int seq_path(struct seq_file *m, const struct path *path, const char *esc)
     471             : {
     472             :         char *buf;
     473           0 :         size_t size = seq_get_buf(m, &buf);
     474           0 :         int res = -1;
     475             : 
     476           0 :         if (size) {
     477           0 :                 char *p = d_path(path, buf, size);
     478           0 :                 if (!IS_ERR(p)) {
     479           0 :                         char *end = mangle_path(buf, p, esc);
     480           0 :                         if (end)
     481           0 :                                 res = end - buf;
     482             :                 }
     483             :         }
     484           0 :         seq_commit(m, res);
     485             : 
     486           0 :         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           0 : int seq_file_path(struct seq_file *m, struct file *file, const char *esc)
     499             : {
     500           0 :         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           0 : int seq_path_root(struct seq_file *m, const struct path *path,
     508             :                   const struct path *root, const char *esc)
     509             : {
     510             :         char *buf;
     511           0 :         size_t size = seq_get_buf(m, &buf);
     512           0 :         int res = -ENAMETOOLONG;
     513             : 
     514           0 :         if (size) {
     515             :                 char *p;
     516             : 
     517           0 :                 p = __d_path(path, root, buf, size);
     518           0 :                 if (!p)
     519             :                         return SEQ_SKIP;
     520           0 :                 res = PTR_ERR(p);
     521           0 :                 if (!IS_ERR(p)) {
     522           0 :                         char *end = mangle_path(buf, p, esc);
     523           0 :                         if (end)
     524           0 :                                 res = end - buf;
     525             :                         else
     526             :                                 res = -ENAMETOOLONG;
     527             :                 }
     528             :         }
     529           0 :         seq_commit(m, res);
     530             : 
     531           0 :         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           0 : int seq_dentry(struct seq_file *m, struct dentry *dentry, const char *esc)
     538             : {
     539             :         char *buf;
     540           0 :         size_t size = seq_get_buf(m, &buf);
     541           0 :         int res = -1;
     542             : 
     543           0 :         if (size) {
     544           0 :                 char *p = dentry_path(dentry, buf, size);
     545           0 :                 if (!IS_ERR(p)) {
     546           0 :                         char *end = mangle_path(buf, p, esc);
     547           0 :                         if (end)
     548           0 :                                 res = end - buf;
     549             :                 }
     550             :         }
     551           0 :         seq_commit(m, res);
     552             : 
     553           0 :         return res;
     554             : }
     555             : EXPORT_SYMBOL(seq_dentry);
     556             : 
     557           0 : void *single_start(struct seq_file *p, loff_t *pos)
     558             : {
     559           0 :         return *pos ? NULL : SEQ_START_TOKEN;
     560             : }
     561             : 
     562           0 : static void *single_next(struct seq_file *p, void *v, loff_t *pos)
     563             : {
     564           0 :         ++*pos;
     565           0 :         return NULL;
     566             : }
     567             : 
     568           0 : static void single_stop(struct seq_file *p, void *v)
     569             : {
     570           0 : }
     571             : 
     572           0 : int single_open(struct file *file, int (*show)(struct seq_file *, void *),
     573             :                 void *data)
     574             : {
     575           0 :         struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
     576           0 :         int res = -ENOMEM;
     577             : 
     578           0 :         if (op) {
     579           0 :                 op->start = single_start;
     580           0 :                 op->next = single_next;
     581           0 :                 op->stop = single_stop;
     582           0 :                 op->show = show;
     583           0 :                 res = seq_open(file, op);
     584           0 :                 if (!res)
     585           0 :                         ((struct seq_file *)file->private_data)->private = data;
     586             :                 else
     587           0 :                         kfree(op);
     588             :         }
     589           0 :         return res;
     590             : }
     591             : EXPORT_SYMBOL(single_open);
     592             : 
     593           0 : int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
     594             :                 void *data, size_t size)
     595             : {
     596           0 :         char *buf = seq_buf_alloc(size);
     597             :         int ret;
     598           0 :         if (!buf)
     599             :                 return -ENOMEM;
     600           0 :         ret = single_open(file, show, data);
     601           0 :         if (ret) {
     602           0 :                 kvfree(buf);
     603           0 :                 return ret;
     604             :         }
     605           0 :         ((struct seq_file *)file->private_data)->buf = buf;
     606           0 :         ((struct seq_file *)file->private_data)->size = size;
     607           0 :         return 0;
     608             : }
     609             : EXPORT_SYMBOL(single_open_size);
     610             : 
     611           0 : int single_release(struct inode *inode, struct file *file)
     612             : {
     613           0 :         const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
     614           0 :         int res = seq_release(inode, file);
     615           0 :         kfree(op);
     616           0 :         return res;
     617             : }
     618             : EXPORT_SYMBOL(single_release);
     619             : 
     620           0 : int seq_release_private(struct inode *inode, struct file *file)
     621             : {
     622           0 :         struct seq_file *seq = file->private_data;
     623             : 
     624           0 :         kfree(seq->private);
     625           0 :         seq->private = NULL;
     626           0 :         return seq_release(inode, file);
     627             : }
     628             : EXPORT_SYMBOL(seq_release_private);
     629             : 
     630           0 : void *__seq_open_private(struct file *f, const struct seq_operations *ops,
     631             :                 int psize)
     632             : {
     633             :         int rc;
     634             :         void *private;
     635             :         struct seq_file *seq;
     636             : 
     637           0 :         private = kzalloc(psize, GFP_KERNEL_ACCOUNT);
     638           0 :         if (private == NULL)
     639             :                 goto out;
     640             : 
     641           0 :         rc = seq_open(f, ops);
     642           0 :         if (rc < 0)
     643             :                 goto out_free;
     644             : 
     645           0 :         seq = f->private_data;
     646           0 :         seq->private = private;
     647           0 :         return private;
     648             : 
     649             : out_free:
     650           0 :         kfree(private);
     651             : out:
     652             :         return NULL;
     653             : }
     654             : EXPORT_SYMBOL(__seq_open_private);
     655             : 
     656           0 : int seq_open_private(struct file *filp, const struct seq_operations *ops,
     657             :                 int psize)
     658             : {
     659           0 :         return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
     660             : }
     661             : EXPORT_SYMBOL(seq_open_private);
     662             : 
     663           0 : void seq_putc(struct seq_file *m, char c)
     664             : {
     665           0 :         if (m->count >= m->size)
     666             :                 return;
     667             : 
     668           0 :         m->buf[m->count++] = c;
     669             : }
     670             : EXPORT_SYMBOL(seq_putc);
     671             : 
     672           0 : void seq_puts(struct seq_file *m, const char *s)
     673             : {
     674           0 :         int len = strlen(s);
     675             : 
     676           0 :         if (m->count + len >= m->size) {
     677           0 :                 seq_set_overflow(m);
     678             :                 return;
     679             :         }
     680           0 :         memcpy(m->buf + m->count, s, len);
     681           0 :         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           0 : void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
     699             :                          unsigned long long num, unsigned int width)
     700             : {
     701             :         int len;
     702             : 
     703           0 :         if (m->count + 2 >= m->size) /* we'll write 2 bytes at least */
     704             :                 goto overflow;
     705             : 
     706           0 :         if (delimiter && delimiter[0]) {
     707           0 :                 if (delimiter[1] == 0)
     708           0 :                         seq_putc(m, delimiter[0]);
     709             :                 else
     710           0 :                         seq_puts(m, delimiter);
     711             :         }
     712             : 
     713           0 :         if (!width)
     714           0 :                 width = 1;
     715             : 
     716           0 :         if (m->count + width >= m->size)
     717             :                 goto overflow;
     718             : 
     719           0 :         len = num_to_str(m->buf + m->count, m->size - m->count, num, width);
     720           0 :         if (!len)
     721             :                 goto overflow;
     722             : 
     723           0 :         m->count += len;
     724           0 :         return;
     725             : 
     726             : overflow:
     727           0 :         seq_set_overflow(m);
     728             : }
     729             : 
     730           0 : void seq_put_decimal_ull(struct seq_file *m, const char *delimiter,
     731             :                          unsigned long long num)
     732             : {
     733           0 :         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           0 : void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
     750             :                                 unsigned long long v, unsigned int width)
     751             : {
     752             :         unsigned int len;
     753             :         int i;
     754             : 
     755           0 :         if (delimiter && delimiter[0]) {
     756           0 :                 if (delimiter[1] == 0)
     757           0 :                         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           0 :         if (v == 0)
     764             :                 len = 1;
     765             :         else
     766           0 :                 len = (sizeof(v) * 8 - __builtin_clzll(v) + 3) / 4;
     767             : 
     768           0 :         if (len < width)
     769           0 :                 len = width;
     770             : 
     771           0 :         if (m->count + len > m->size) {
     772           0 :                 seq_set_overflow(m);
     773             :                 return;
     774             :         }
     775             : 
     776           0 :         for (i = len - 1; i >= 0; i--) {
     777           0 :                 m->buf[m->count + i] = hex_asc[0xf & v];
     778           0 :                 v = v >> 4;
     779             :         }
     780           0 :         m->count += len;
     781             : }
     782             : 
     783           0 : void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
     784             : {
     785             :         int len;
     786             : 
     787           0 :         if (m->count + 3 >= m->size) /* we'll write 2 bytes at least */
     788             :                 goto overflow;
     789             : 
     790           0 :         if (delimiter && delimiter[0]) {
     791           0 :                 if (delimiter[1] == 0)
     792           0 :                         seq_putc(m, delimiter[0]);
     793             :                 else
     794           0 :                         seq_puts(m, delimiter);
     795             :         }
     796             : 
     797           0 :         if (m->count + 2 >= m->size)
     798             :                 goto overflow;
     799             : 
     800           0 :         if (num < 0) {
     801           0 :                 m->buf[m->count++] = '-';
     802           0 :                 num = -num;
     803             :         }
     804             : 
     805           0 :         if (num < 10) {
     806           0 :                 m->buf[m->count++] = num + '0';
     807           0 :                 return;
     808             :         }
     809             : 
     810           0 :         len = num_to_str(m->buf + m->count, m->size - m->count, num, 0);
     811           0 :         if (!len)
     812             :                 goto overflow;
     813             : 
     814           0 :         m->count += len;
     815           0 :         return;
     816             : 
     817             : 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           0 : int seq_write(struct seq_file *seq, const void *data, size_t len)
     831             : {
     832           0 :         if (seq->count + len < seq->size) {
     833           0 :                 memcpy(seq->buf + seq->count, data, len);
     834           0 :                 seq->count += len;
     835           0 :                 return 0;
     836             :         }
     837           0 :         seq_set_overflow(seq);
     838           0 :         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           0 : void seq_pad(struct seq_file *m, char c)
     848             : {
     849           0 :         int size = m->pad_until - m->count;
     850           0 :         if (size > 0) {
     851           0 :                 if (size + m->count > m->size) {
     852           0 :                         seq_set_overflow(m);
     853             :                         return;
     854             :                 }
     855           0 :                 memset(m->buf + m->count, ' ', size);
     856           0 :                 m->count += size;
     857             :         }
     858           0 :         if (c)
     859           0 :                 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             :         char *buffer;
     871             :         size_t size;
     872             :         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             :                 case DUMP_PREFIX_ADDRESS:
     883           0 :                         seq_printf(m, "%s%p: ", prefix_str, ptr + i);
     884           0 :                         break;
     885             :                 case DUMP_PREFIX_OFFSET:
     886           0 :                         seq_printf(m, "%s%.8x: ", prefix_str, i);
     887           0 :                         break;
     888             :                 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           0 : struct list_head *seq_list_start(struct list_head *head, loff_t pos)
     904             : {
     905             :         struct list_head *lh;
     906             : 
     907           0 :         list_for_each(lh, head)
     908           0 :                 if (pos-- == 0)
     909             :                         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           0 : struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
     925             : {
     926             :         struct list_head *lh;
     927             : 
     928           0 :         lh = ((struct list_head *)v)->next;
     929           0 :         ++*ppos;
     930           0 :         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             :         struct list_head *lh;
     937             : 
     938           0 :         list_for_each_rcu(lh, head)
     939           0 :                 if (pos-- == 0)
     940             :                         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             :         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             :         struct hlist_node *node;
     976             : 
     977           0 :         hlist_for_each(node, head)
     978           0 :                 if (pos-- == 0)
     979             :                         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             :         struct hlist_node *node;
    1037             : 
    1038           0 :         __hlist_for_each_rcu(node, head)
    1039           0 :                 if (pos-- == 0)
    1040             :                         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           0 : seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
    1103             : {
    1104             :         struct hlist_node *node;
    1105             : 
    1106           0 :         for_each_possible_cpu(*cpu) {
    1107           0 :                 hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
    1108           0 :                         if (pos-- == 0)
    1109             :                                 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           0 : seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
    1127             :                         int *cpu, loff_t *pos)
    1128             : {
    1129           0 :         struct hlist_node *node = v;
    1130             : 
    1131           0 :         ++*pos;
    1132             : 
    1133           0 :         if (node->next)
    1134             :                 return node->next;
    1135             : 
    1136           0 :         for (*cpu = cpumask_next(*cpu, cpu_possible_mask); *cpu < nr_cpu_ids;
    1137           0 :              *cpu = cpumask_next(*cpu, cpu_possible_mask)) {
    1138           0 :                 struct hlist_head *bucket = per_cpu_ptr(head, *cpu);
    1139             : 
    1140           0 :                 if (!hlist_empty(bucket))
    1141           0 :                         return bucket->first;
    1142             :         }
    1143             :         return NULL;
    1144             : }
    1145             : EXPORT_SYMBOL(seq_hlist_next_percpu);
    1146             : 
    1147           1 : void __init seq_file_init(void)
    1148             : {
    1149           1 :         seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT|SLAB_PANIC);
    1150           1 : }

Generated by: LCOV version 1.14