The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/seq_file.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * linux/fs/seq_file.c
    3  *
    4  * helper functions for making synthetic files from sequences of records.
    5  * initial implementation -- AV, Oct 2001.
    6  */
    7 
    8 #include <linux/fs.h>
    9 #include <linux/export.h>
   10 #include <linux/seq_file.h>
   11 #include <linux/slab.h>
   12 #include <linux/cred.h>
   13 
   14 #include <asm/uaccess.h>
   15 #include <asm/page.h>
   16 
   17 
   18 /*
   19  * seq_files have a buffer which can may overflow. When this happens a larger
   20  * buffer is reallocated and all the data will be printed again.
   21  * The overflow state is true when m->count == m->size.
   22  */
   23 static bool seq_overflow(struct seq_file *m)
   24 {
   25         return m->count == m->size;
   26 }
   27 
   28 static void seq_set_overflow(struct seq_file *m)
   29 {
   30         m->count = m->size;
   31 }
   32 
   33 /**
   34  *      seq_open -      initialize sequential file
   35  *      @file: file we initialize
   36  *      @op: method table describing the sequence
   37  *
   38  *      seq_open() sets @file, associating it with a sequence described
   39  *      by @op.  @op->start() sets the iterator up and returns the first
   40  *      element of sequence. @op->stop() shuts it down.  @op->next()
   41  *      returns the next element of sequence.  @op->show() prints element
   42  *      into the buffer.  In case of error ->start() and ->next() return
   43  *      ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
   44  *      returns 0 in case of success and negative number in case of error.
   45  *      Returning SEQ_SKIP means "discard this element and move on".
   46  */
   47 int seq_open(struct file *file, const struct seq_operations *op)
   48 {
   49         struct seq_file *p = file->private_data;
   50 
   51         if (!p) {
   52                 p = kmalloc(sizeof(*p), GFP_KERNEL);
   53                 if (!p)
   54                         return -ENOMEM;
   55                 file->private_data = p;
   56         }
   57         memset(p, 0, sizeof(*p));
   58         mutex_init(&p->lock);
   59         p->op = op;
   60 #ifdef CONFIG_USER_NS
   61         p->user_ns = file->f_cred->user_ns;
   62 #endif
   63 
   64         /*
   65          * Wrappers around seq_open(e.g. swaps_open) need to be
   66          * aware of this. If they set f_version themselves, they
   67          * should call seq_open first and then set f_version.
   68          */
   69         file->f_version = 0;
   70 
   71         /*
   72          * seq_files support lseek() and pread().  They do not implement
   73          * write() at all, but we clear FMODE_PWRITE here for historical
   74          * reasons.
   75          *
   76          * If a client of seq_files a) implements file.write() and b) wishes to
   77          * support pwrite() then that client will need to implement its own
   78          * file.open() which calls seq_open() and then sets FMODE_PWRITE.
   79          */
   80         file->f_mode &= ~FMODE_PWRITE;
   81         return 0;
   82 }
   83 EXPORT_SYMBOL(seq_open);
   84 
   85 static int traverse(struct seq_file *m, loff_t offset)
   86 {
   87         loff_t pos = 0, index;
   88         int error = 0;
   89         void *p;
   90 
   91         m->version = 0;
   92         index = 0;
   93         m->count = m->from = 0;
   94         if (!offset) {
   95                 m->index = index;
   96                 return 0;
   97         }
   98         if (!m->buf) {
   99                 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
  100                 if (!m->buf)
  101                         return -ENOMEM;
  102         }
  103         p = m->op->start(m, &index);
  104         while (p) {
  105                 error = PTR_ERR(p);
  106                 if (IS_ERR(p))
  107                         break;
  108                 error = m->op->show(m, p);
  109                 if (error < 0)
  110                         break;
  111                 if (unlikely(error)) {
  112                         error = 0;
  113                         m->count = 0;
  114                 }
  115                 if (seq_overflow(m))
  116                         goto Eoverflow;
  117                 if (pos + m->count > offset) {
  118                         m->from = offset - pos;
  119                         m->count -= m->from;
  120                         m->index = index;
  121                         break;
  122                 }
  123                 pos += m->count;
  124                 m->count = 0;
  125                 if (pos == offset) {
  126                         index++;
  127                         m->index = index;
  128                         break;
  129                 }
  130                 p = m->op->next(m, p, &index);
  131         }
  132         m->op->stop(m, p);
  133         m->index = index;
  134         return error;
  135 
  136 Eoverflow:
  137         m->op->stop(m, p);
  138         kfree(m->buf);
  139         m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
  140         return !m->buf ? -ENOMEM : -EAGAIN;
  141 }
  142 
  143 /**
  144  *      seq_read -      ->read() method for sequential files.
  145  *      @file: the file to read from
  146  *      @buf: the buffer to read to
  147  *      @size: the maximum number of bytes to read
  148  *      @ppos: the current position in the file
  149  *
  150  *      Ready-made ->f_op->read()
  151  */
  152 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
  153 {
  154         struct seq_file *m = file->private_data;
  155         size_t copied = 0;
  156         loff_t pos;
  157         size_t n;
  158         void *p;
  159         int err = 0;
  160 
  161         mutex_lock(&m->lock);
  162 
  163         /*
  164          * seq_file->op->..m_start/m_stop/m_next may do special actions
  165          * or optimisations based on the file->f_version, so we want to
  166          * pass the file->f_version to those methods.
  167          *
  168          * seq_file->version is just copy of f_version, and seq_file
  169          * methods can treat it simply as file version.
  170          * It is copied in first and copied out after all operations.
  171          * It is convenient to have it as  part of structure to avoid the
  172          * need of passing another argument to all the seq_file methods.
  173          */
  174         m->version = file->f_version;
  175 
  176         /* Don't assume *ppos is where we left it */
  177         if (unlikely(*ppos != m->read_pos)) {
  178                 while ((err = traverse(m, *ppos)) == -EAGAIN)
  179                         ;
  180                 if (err) {
  181                         /* With prejudice... */
  182                         m->read_pos = 0;
  183                         m->version = 0;
  184                         m->index = 0;
  185                         m->count = 0;
  186                         goto Done;
  187                 } else {
  188                         m->read_pos = *ppos;
  189                 }
  190         }
  191 
  192         /* grab buffer if we didn't have one */
  193         if (!m->buf) {
  194                 m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
  195                 if (!m->buf)
  196                         goto Enomem;
  197         }
  198         /* if not empty - flush it first */
  199         if (m->count) {
  200                 n = min(m->count, size);
  201                 err = copy_to_user(buf, m->buf + m->from, n);
  202                 if (err)
  203                         goto Efault;
  204                 m->count -= n;
  205                 m->from += n;
  206                 size -= n;
  207                 buf += n;
  208                 copied += n;
  209                 if (!m->count)
  210                         m->index++;
  211                 if (!size)
  212                         goto Done;
  213         }
  214         /* we need at least one record in buffer */
  215         pos = m->index;
  216         p = m->op->start(m, &pos);
  217         while (1) {
  218                 err = PTR_ERR(p);
  219                 if (!p || IS_ERR(p))
  220                         break;
  221                 err = m->op->show(m, p);
  222                 if (err < 0)
  223                         break;
  224                 if (unlikely(err))
  225                         m->count = 0;
  226                 if (unlikely(!m->count)) {
  227                         p = m->op->next(m, p, &pos);
  228                         m->index = pos;
  229                         continue;
  230                 }
  231                 if (m->count < m->size)
  232                         goto Fill;
  233                 m->op->stop(m, p);
  234                 kfree(m->buf);
  235                 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
  236                 if (!m->buf)
  237                         goto Enomem;
  238                 m->count = 0;
  239                 m->version = 0;
  240                 pos = m->index;
  241                 p = m->op->start(m, &pos);
  242         }
  243         m->op->stop(m, p);
  244         m->count = 0;
  245         goto Done;
  246 Fill:
  247         /* they want more? let's try to get some more */
  248         while (m->count < size) {
  249                 size_t offs = m->count;
  250                 loff_t next = pos;
  251                 p = m->op->next(m, p, &next);
  252                 if (!p || IS_ERR(p)) {
  253                         err = PTR_ERR(p);
  254                         break;
  255                 }
  256                 err = m->op->show(m, p);
  257                 if (seq_overflow(m) || err) {
  258                         m->count = offs;
  259                         if (likely(err <= 0))
  260                                 break;
  261                 }
  262                 pos = next;
  263         }
  264         m->op->stop(m, p);
  265         n = min(m->count, size);
  266         err = copy_to_user(buf, m->buf, n);
  267         if (err)
  268                 goto Efault;
  269         copied += n;
  270         m->count -= n;
  271         if (m->count)
  272                 m->from = n;
  273         else
  274                 pos++;
  275         m->index = pos;
  276 Done:
  277         if (!copied)
  278                 copied = err;
  279         else {
  280                 *ppos += copied;
  281                 m->read_pos += copied;
  282         }
  283         file->f_version = m->version;
  284         mutex_unlock(&m->lock);
  285         return copied;
  286 Enomem:
  287         err = -ENOMEM;
  288         goto Done;
  289 Efault:
  290         err = -EFAULT;
  291         goto Done;
  292 }
  293 EXPORT_SYMBOL(seq_read);
  294 
  295 /**
  296  *      seq_lseek -     ->llseek() method for sequential files.
  297  *      @file: the file in question
  298  *      @offset: new position
  299  *      @whence: 0 for absolute, 1 for relative position
  300  *
  301  *      Ready-made ->f_op->llseek()
  302  */
  303 loff_t seq_lseek(struct file *file, loff_t offset, int whence)
  304 {
  305         struct seq_file *m = file->private_data;
  306         loff_t retval = -EINVAL;
  307 
  308         mutex_lock(&m->lock);
  309         m->version = file->f_version;
  310         switch (whence) {
  311                 case 1:
  312                         offset += file->f_pos;
  313                 case 0:
  314                         if (offset < 0)
  315                                 break;
  316                         retval = offset;
  317                         if (offset != m->read_pos) {
  318                                 while ((retval=traverse(m, offset)) == -EAGAIN)
  319                                         ;
  320                                 if (retval) {
  321                                         /* with extreme prejudice... */
  322                                         file->f_pos = 0;
  323                                         m->read_pos = 0;
  324                                         m->version = 0;
  325                                         m->index = 0;
  326                                         m->count = 0;
  327                                 } else {
  328                                         m->read_pos = offset;
  329                                         retval = file->f_pos = offset;
  330                                 }
  331                         }
  332         }
  333         file->f_version = m->version;
  334         mutex_unlock(&m->lock);
  335         return retval;
  336 }
  337 EXPORT_SYMBOL(seq_lseek);
  338 
  339 /**
  340  *      seq_release -   free the structures associated with sequential file.
  341  *      @file: file in question
  342  *      @inode: file->f_path.dentry->d_inode
  343  *
  344  *      Frees the structures associated with sequential file; can be used
  345  *      as ->f_op->release() if you don't have private data to destroy.
  346  */
  347 int seq_release(struct inode *inode, struct file *file)
  348 {
  349         struct seq_file *m = file->private_data;
  350         kfree(m->buf);
  351         kfree(m);
  352         return 0;
  353 }
  354 EXPORT_SYMBOL(seq_release);
  355 
  356 /**
  357  *      seq_escape -    print string into buffer, escaping some characters
  358  *      @m:     target buffer
  359  *      @s:     string
  360  *      @esc:   set of characters that need escaping
  361  *
  362  *      Puts string into buffer, replacing each occurrence of character from
  363  *      @esc with usual octal escape.  Returns 0 in case of success, -1 - in
  364  *      case of overflow.
  365  */
  366 int seq_escape(struct seq_file *m, const char *s, const char *esc)
  367 {
  368         char *end = m->buf + m->size;
  369         char *p;
  370         char c;
  371 
  372         for (p = m->buf + m->count; (c = *s) != '\0' && p < end; s++) {
  373                 if (!strchr(esc, c)) {
  374                         *p++ = c;
  375                         continue;
  376                 }
  377                 if (p + 3 < end) {
  378                         *p++ = '\\';
  379                         *p++ = '' + ((c & 0300) >> 6);
  380                         *p++ = '' + ((c & 070) >> 3);
  381                         *p++ = '' + (c & 07);
  382                         continue;
  383                 }
  384                 seq_set_overflow(m);
  385                 return -1;
  386         }
  387         m->count = p - m->buf;
  388         return 0;
  389 }
  390 EXPORT_SYMBOL(seq_escape);
  391 
  392 int seq_vprintf(struct seq_file *m, const char *f, va_list args)
  393 {
  394         int len;
  395 
  396         if (m->count < m->size) {
  397                 len = vsnprintf(m->buf + m->count, m->size - m->count, f, args);
  398                 if (m->count + len < m->size) {
  399                         m->count += len;
  400                         return 0;
  401                 }
  402         }
  403         seq_set_overflow(m);
  404         return -1;
  405 }
  406 EXPORT_SYMBOL(seq_vprintf);
  407 
  408 int seq_printf(struct seq_file *m, const char *f, ...)
  409 {
  410         int ret;
  411         va_list args;
  412 
  413         va_start(args, f);
  414         ret = seq_vprintf(m, f, args);
  415         va_end(args);
  416 
  417         return ret;
  418 }
  419 EXPORT_SYMBOL(seq_printf);
  420 
  421 /**
  422  *      mangle_path -   mangle and copy path to buffer beginning
  423  *      @s: buffer start
  424  *      @p: beginning of path in above buffer
  425  *      @esc: set of characters that need escaping
  426  *
  427  *      Copy the path from @p to @s, replacing each occurrence of character from
  428  *      @esc with usual octal escape.
  429  *      Returns pointer past last written character in @s, or NULL in case of
  430  *      failure.
  431  */
  432 char *mangle_path(char *s, const char *p, const char *esc)
  433 {
  434         while (s <= p) {
  435                 char c = *p++;
  436                 if (!c) {
  437                         return s;
  438                 } else if (!strchr(esc, c)) {
  439                         *s++ = c;
  440                 } else if (s + 4 > p) {
  441                         break;
  442                 } else {
  443                         *s++ = '\\';
  444                         *s++ = '' + ((c & 0300) >> 6);
  445                         *s++ = '' + ((c & 070) >> 3);
  446                         *s++ = '' + (c & 07);
  447                 }
  448         }
  449         return NULL;
  450 }
  451 EXPORT_SYMBOL(mangle_path);
  452 
  453 /**
  454  * seq_path - seq_file interface to print a pathname
  455  * @m: the seq_file handle
  456  * @path: the struct path to print
  457  * @esc: set of characters to escape in the output
  458  *
  459  * return the absolute path of 'path', as represented by the
  460  * dentry / mnt pair in the path parameter.
  461  */
  462 int seq_path(struct seq_file *m, const struct path *path, const char *esc)
  463 {
  464         char *buf;
  465         size_t size = seq_get_buf(m, &buf);
  466         int res = -1;
  467 
  468         if (size) {
  469                 char *p = d_path(path, buf, size);
  470                 if (!IS_ERR(p)) {
  471                         char *end = mangle_path(buf, p, esc);
  472                         if (end)
  473                                 res = end - buf;
  474                 }
  475         }
  476         seq_commit(m, res);
  477 
  478         return res;
  479 }
  480 EXPORT_SYMBOL(seq_path);
  481 
  482 /*
  483  * Same as seq_path, but relative to supplied root.
  484  */
  485 int seq_path_root(struct seq_file *m, const struct path *path,
  486                   const struct path *root, const char *esc)
  487 {
  488         char *buf;
  489         size_t size = seq_get_buf(m, &buf);
  490         int res = -ENAMETOOLONG;
  491 
  492         if (size) {
  493                 char *p;
  494 
  495                 p = __d_path(path, root, buf, size);
  496                 if (!p)
  497                         return SEQ_SKIP;
  498                 res = PTR_ERR(p);
  499                 if (!IS_ERR(p)) {
  500                         char *end = mangle_path(buf, p, esc);
  501                         if (end)
  502                                 res = end - buf;
  503                         else
  504                                 res = -ENAMETOOLONG;
  505                 }
  506         }
  507         seq_commit(m, res);
  508 
  509         return res < 0 && res != -ENAMETOOLONG ? res : 0;
  510 }
  511 
  512 /*
  513  * returns the path of the 'dentry' from the root of its filesystem.
  514  */
  515 int seq_dentry(struct seq_file *m, struct dentry *dentry, const char *esc)
  516 {
  517         char *buf;
  518         size_t size = seq_get_buf(m, &buf);
  519         int res = -1;
  520 
  521         if (size) {
  522                 char *p = dentry_path(dentry, buf, size);
  523                 if (!IS_ERR(p)) {
  524                         char *end = mangle_path(buf, p, esc);
  525                         if (end)
  526                                 res = end - buf;
  527                 }
  528         }
  529         seq_commit(m, res);
  530 
  531         return res;
  532 }
  533 
  534 int seq_bitmap(struct seq_file *m, const unsigned long *bits,
  535                                    unsigned int nr_bits)
  536 {
  537         if (m->count < m->size) {
  538                 int len = bitmap_scnprintf(m->buf + m->count,
  539                                 m->size - m->count, bits, nr_bits);
  540                 if (m->count + len < m->size) {
  541                         m->count += len;
  542                         return 0;
  543                 }
  544         }
  545         seq_set_overflow(m);
  546         return -1;
  547 }
  548 EXPORT_SYMBOL(seq_bitmap);
  549 
  550 int seq_bitmap_list(struct seq_file *m, const unsigned long *bits,
  551                 unsigned int nr_bits)
  552 {
  553         if (m->count < m->size) {
  554                 int len = bitmap_scnlistprintf(m->buf + m->count,
  555                                 m->size - m->count, bits, nr_bits);
  556                 if (m->count + len < m->size) {
  557                         m->count += len;
  558                         return 0;
  559                 }
  560         }
  561         seq_set_overflow(m);
  562         return -1;
  563 }
  564 EXPORT_SYMBOL(seq_bitmap_list);
  565 
  566 static void *single_start(struct seq_file *p, loff_t *pos)
  567 {
  568         return NULL + (*pos == 0);
  569 }
  570 
  571 static void *single_next(struct seq_file *p, void *v, loff_t *pos)
  572 {
  573         ++*pos;
  574         return NULL;
  575 }
  576 
  577 static void single_stop(struct seq_file *p, void *v)
  578 {
  579 }
  580 
  581 int single_open(struct file *file, int (*show)(struct seq_file *, void *),
  582                 void *data)
  583 {
  584         struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL);
  585         int res = -ENOMEM;
  586 
  587         if (op) {
  588                 op->start = single_start;
  589                 op->next = single_next;
  590                 op->stop = single_stop;
  591                 op->show = show;
  592                 res = seq_open(file, op);
  593                 if (!res)
  594                         ((struct seq_file *)file->private_data)->private = data;
  595                 else
  596                         kfree(op);
  597         }
  598         return res;
  599 }
  600 EXPORT_SYMBOL(single_open);
  601 
  602 int single_release(struct inode *inode, struct file *file)
  603 {
  604         const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
  605         int res = seq_release(inode, file);
  606         kfree(op);
  607         return res;
  608 }
  609 EXPORT_SYMBOL(single_release);
  610 
  611 int seq_release_private(struct inode *inode, struct file *file)
  612 {
  613         struct seq_file *seq = file->private_data;
  614 
  615         kfree(seq->private);
  616         seq->private = NULL;
  617         return seq_release(inode, file);
  618 }
  619 EXPORT_SYMBOL(seq_release_private);
  620 
  621 void *__seq_open_private(struct file *f, const struct seq_operations *ops,
  622                 int psize)
  623 {
  624         int rc;
  625         void *private;
  626         struct seq_file *seq;
  627 
  628         private = kzalloc(psize, GFP_KERNEL);
  629         if (private == NULL)
  630                 goto out;
  631 
  632         rc = seq_open(f, ops);
  633         if (rc < 0)
  634                 goto out_free;
  635 
  636         seq = f->private_data;
  637         seq->private = private;
  638         return private;
  639 
  640 out_free:
  641         kfree(private);
  642 out:
  643         return NULL;
  644 }
  645 EXPORT_SYMBOL(__seq_open_private);
  646 
  647 int seq_open_private(struct file *filp, const struct seq_operations *ops,
  648                 int psize)
  649 {
  650         return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
  651 }
  652 EXPORT_SYMBOL(seq_open_private);
  653 
  654 int seq_putc(struct seq_file *m, char c)
  655 {
  656         if (m->count < m->size) {
  657                 m->buf[m->count++] = c;
  658                 return 0;
  659         }
  660         return -1;
  661 }
  662 EXPORT_SYMBOL(seq_putc);
  663 
  664 int seq_puts(struct seq_file *m, const char *s)
  665 {
  666         int len = strlen(s);
  667         if (m->count + len < m->size) {
  668                 memcpy(m->buf + m->count, s, len);
  669                 m->count += len;
  670                 return 0;
  671         }
  672         seq_set_overflow(m);
  673         return -1;
  674 }
  675 EXPORT_SYMBOL(seq_puts);
  676 
  677 /*
  678  * A helper routine for putting decimal numbers without rich format of printf().
  679  * only 'unsigned long long' is supported.
  680  * This routine will put one byte delimiter + number into seq_file.
  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 int seq_put_decimal_ull(struct seq_file *m, char delimiter,
  685                         unsigned long long num)
  686 {
  687         int len;
  688 
  689         if (m->count + 2 >= m->size) /* we'll write 2 bytes at least */
  690                 goto overflow;
  691 
  692         if (delimiter)
  693                 m->buf[m->count++] = delimiter;
  694 
  695         if (num < 10) {
  696                 m->buf[m->count++] = num + '';
  697                 return 0;
  698         }
  699 
  700         len = num_to_str(m->buf + m->count, m->size - m->count, num);
  701         if (!len)
  702                 goto overflow;
  703         m->count += len;
  704         return 0;
  705 overflow:
  706         seq_set_overflow(m);
  707         return -1;
  708 }
  709 EXPORT_SYMBOL(seq_put_decimal_ull);
  710 
  711 int seq_put_decimal_ll(struct seq_file *m, char delimiter,
  712                         long long num)
  713 {
  714         if (num < 0) {
  715                 if (m->count + 3 >= m->size) {
  716                         seq_set_overflow(m);
  717                         return -1;
  718                 }
  719                 if (delimiter)
  720                         m->buf[m->count++] = delimiter;
  721                 num = -num;
  722                 delimiter = '-';
  723         }
  724         return seq_put_decimal_ull(m, delimiter, num);
  725 
  726 }
  727 EXPORT_SYMBOL(seq_put_decimal_ll);
  728 
  729 /**
  730  * seq_write - write arbitrary data to buffer
  731  * @seq: seq_file identifying the buffer to which data should be written
  732  * @data: data address
  733  * @len: number of bytes
  734  *
  735  * Return 0 on success, non-zero otherwise.
  736  */
  737 int seq_write(struct seq_file *seq, const void *data, size_t len)
  738 {
  739         if (seq->count + len < seq->size) {
  740                 memcpy(seq->buf + seq->count, data, len);
  741                 seq->count += len;
  742                 return 0;
  743         }
  744         seq_set_overflow(seq);
  745         return -1;
  746 }
  747 EXPORT_SYMBOL(seq_write);
  748 
  749 struct list_head *seq_list_start(struct list_head *head, loff_t pos)
  750 {
  751         struct list_head *lh;
  752 
  753         list_for_each(lh, head)
  754                 if (pos-- == 0)
  755                         return lh;
  756 
  757         return NULL;
  758 }
  759 EXPORT_SYMBOL(seq_list_start);
  760 
  761 struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
  762 {
  763         if (!pos)
  764                 return head;
  765 
  766         return seq_list_start(head, pos - 1);
  767 }
  768 EXPORT_SYMBOL(seq_list_start_head);
  769 
  770 struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
  771 {
  772         struct list_head *lh;
  773 
  774         lh = ((struct list_head *)v)->next;
  775         ++*ppos;
  776         return lh == head ? NULL : lh;
  777 }
  778 EXPORT_SYMBOL(seq_list_next);
  779 
  780 /**
  781  * seq_hlist_start - start an iteration of a hlist
  782  * @head: the head of the hlist
  783  * @pos:  the start position of the sequence
  784  *
  785  * Called at seq_file->op->start().
  786  */
  787 struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
  788 {
  789         struct hlist_node *node;
  790 
  791         hlist_for_each(node, head)
  792                 if (pos-- == 0)
  793                         return node;
  794         return NULL;
  795 }
  796 EXPORT_SYMBOL(seq_hlist_start);
  797 
  798 /**
  799  * seq_hlist_start_head - start an iteration of a hlist
  800  * @head: the head of the hlist
  801  * @pos:  the start position of the sequence
  802  *
  803  * Called at seq_file->op->start(). Call this function if you want to
  804  * print a header at the top of the output.
  805  */
  806 struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
  807 {
  808         if (!pos)
  809                 return SEQ_START_TOKEN;
  810 
  811         return seq_hlist_start(head, pos - 1);
  812 }
  813 EXPORT_SYMBOL(seq_hlist_start_head);
  814 
  815 /**
  816  * seq_hlist_next - move to the next position of the hlist
  817  * @v:    the current iterator
  818  * @head: the head of the hlist
  819  * @ppos: the current position
  820  *
  821  * Called at seq_file->op->next().
  822  */
  823 struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
  824                                   loff_t *ppos)
  825 {
  826         struct hlist_node *node = v;
  827 
  828         ++*ppos;
  829         if (v == SEQ_START_TOKEN)
  830                 return head->first;
  831         else
  832                 return node->next;
  833 }
  834 EXPORT_SYMBOL(seq_hlist_next);
  835 
  836 /**
  837  * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
  838  * @head: the head of the hlist
  839  * @pos:  the start position of the sequence
  840  *
  841  * Called at seq_file->op->start().
  842  *
  843  * This list-traversal primitive may safely run concurrently with
  844  * the _rcu list-mutation primitives such as hlist_add_head_rcu()
  845  * as long as the traversal is guarded by rcu_read_lock().
  846  */
  847 struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
  848                                        loff_t pos)
  849 {
  850         struct hlist_node *node;
  851 
  852         __hlist_for_each_rcu(node, head)
  853                 if (pos-- == 0)
  854                         return node;
  855         return NULL;
  856 }
  857 EXPORT_SYMBOL(seq_hlist_start_rcu);
  858 
  859 /**
  860  * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
  861  * @head: the head of the hlist
  862  * @pos:  the start position of the sequence
  863  *
  864  * Called at seq_file->op->start(). Call this function if you want to
  865  * print a header at the top of the output.
  866  *
  867  * This list-traversal primitive may safely run concurrently with
  868  * the _rcu list-mutation primitives such as hlist_add_head_rcu()
  869  * as long as the traversal is guarded by rcu_read_lock().
  870  */
  871 struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
  872                                             loff_t pos)
  873 {
  874         if (!pos)
  875                 return SEQ_START_TOKEN;
  876 
  877         return seq_hlist_start_rcu(head, pos - 1);
  878 }
  879 EXPORT_SYMBOL(seq_hlist_start_head_rcu);
  880 
  881 /**
  882  * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
  883  * @v:    the current iterator
  884  * @head: the head of the hlist
  885  * @ppos: the current position
  886  *
  887  * Called at seq_file->op->next().
  888  *
  889  * This list-traversal primitive may safely run concurrently with
  890  * the _rcu list-mutation primitives such as hlist_add_head_rcu()
  891  * as long as the traversal is guarded by rcu_read_lock().
  892  */
  893 struct hlist_node *seq_hlist_next_rcu(void *v,
  894                                       struct hlist_head *head,
  895                                       loff_t *ppos)
  896 {
  897         struct hlist_node *node = v;
  898 
  899         ++*ppos;
  900         if (v == SEQ_START_TOKEN)
  901                 return rcu_dereference(head->first);
  902         else
  903                 return rcu_dereference(node->next);
  904 }
  905 EXPORT_SYMBOL(seq_hlist_next_rcu);

Cache object: 7cbc1f9789c0ccf4dc162c820fb666d6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.