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/xdr/xdr_mbuf.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  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
    3  * Authors: Doug Rabson <dfr@rabson.org>
    4  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/7.4/sys/xdr/xdr_mbuf.c 178061 2008-04-10 09:39:29Z dfr $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/mbuf.h>
   35 
   36 #include <rpc/types.h>
   37 #include <rpc/xdr.h>
   38 
   39 static void xdrmbuf_destroy(XDR *);
   40 static bool_t xdrmbuf_getlong(XDR *, long *);
   41 static bool_t xdrmbuf_putlong(XDR *, const long *);
   42 static bool_t xdrmbuf_getbytes(XDR *, char *, u_int);
   43 static bool_t xdrmbuf_putbytes(XDR *, const char *, u_int);
   44 /* XXX: w/64-bit pointers, u_int not enough! */
   45 static u_int xdrmbuf_getpos(XDR *);
   46 static bool_t xdrmbuf_setpos(XDR *, u_int);
   47 static int32_t *xdrmbuf_inline(XDR *, u_int);
   48 
   49 static const struct     xdr_ops xdrmbuf_ops = {
   50         xdrmbuf_getlong,
   51         xdrmbuf_putlong,
   52         xdrmbuf_getbytes,
   53         xdrmbuf_putbytes,
   54         xdrmbuf_getpos,
   55         xdrmbuf_setpos,
   56         xdrmbuf_inline,
   57         xdrmbuf_destroy
   58 };
   59 
   60 /*
   61  * The procedure xdrmbuf_create initializes a stream descriptor for a
   62  * mbuf.
   63  */
   64 void
   65 xdrmbuf_create(XDR *xdrs, struct mbuf *m, enum xdr_op op)
   66 {
   67 
   68         xdrs->x_op = op;
   69         xdrs->x_ops = &xdrmbuf_ops;
   70         xdrs->x_base = (char *) m;
   71         if (op == XDR_ENCODE) {
   72                 m = m_last(m);
   73                 xdrs->x_private = m;
   74                 xdrs->x_handy = m->m_len;
   75         } else {
   76                 xdrs->x_private = m;
   77                 xdrs->x_handy = 0;
   78         }
   79 }
   80 
   81 static void
   82 xdrmbuf_destroy(XDR *xdrs)
   83 {
   84 
   85         if (xdrs->x_op == XDR_DECODE && xdrs->x_base) {
   86                 m_freem((struct mbuf *) xdrs->x_base);
   87                 xdrs->x_base = NULL;
   88                 xdrs->x_private = NULL;
   89         }
   90 }
   91 
   92 static bool_t
   93 xdrmbuf_getlong(XDR *xdrs, long *lp)
   94 {
   95         int32_t t;
   96 
   97         xdrmbuf_getbytes(xdrs, (char *) &t, sizeof(int32_t));
   98         *lp = ntohl(t);
   99         return (TRUE);
  100 }
  101 
  102 static bool_t
  103 xdrmbuf_putlong(xdrs, lp)
  104         XDR *xdrs;
  105         const long *lp;
  106 {
  107         int32_t t = htonl(*lp);
  108 
  109         xdrmbuf_putbytes(xdrs, (char *) &t, sizeof(int32_t));
  110         return (TRUE);
  111 }
  112 
  113 static bool_t
  114 xdrmbuf_getbytes(XDR *xdrs, char *addr, u_int len)
  115 {
  116         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  117         size_t sz;
  118 
  119         while (len > 0) {
  120                 /*
  121                  * Make sure we haven't hit the end.
  122                  */
  123                 if (!m) {
  124                         return (FALSE);
  125                 }
  126 
  127                 /*
  128                  * See how much we can get from this mbuf.
  129                  */
  130                 sz = m->m_len - xdrs->x_handy;
  131                 if (sz > len)
  132                         sz = len;
  133                 memcpy(addr, mtod(m, const char *) + xdrs->x_handy, sz);
  134 
  135                 addr += sz;
  136                 xdrs->x_handy += sz;
  137                 len -= sz;
  138 
  139                 if (xdrs->x_handy == m->m_len) {
  140                         m = m->m_next;
  141                         xdrs->x_private = (void *) m;
  142                         xdrs->x_handy = 0;
  143                 }
  144         }
  145         
  146         return (TRUE);
  147 }
  148 
  149 static bool_t
  150 xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len)
  151 {
  152         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  153         struct mbuf *n;
  154         size_t sz;
  155 
  156         while (len > 0) {
  157                 sz = M_TRAILINGSPACE(m) + (m->m_len - xdrs->x_handy);
  158                 if (sz > len)
  159                         sz = len;
  160                 memcpy(mtod(m, char *) + xdrs->x_handy, addr, sz);
  161                 addr += sz;
  162                 xdrs->x_handy += sz;
  163                 if (xdrs->x_handy > m->m_len)
  164                         m->m_len = xdrs->x_handy;
  165                 len -= sz;
  166 
  167                 if (xdrs->x_handy == m->m_len && M_TRAILINGSPACE(m) == 0) {
  168                         if (!m->m_next) {
  169                                 MGET(n, M_TRYWAIT, m->m_type);
  170                                 m->m_next = n;
  171                         }
  172                         m = m->m_next;
  173                         xdrs->x_private = (void *) m;
  174                         xdrs->x_handy = 0;
  175                 }
  176         }
  177         
  178         return (TRUE);
  179 }
  180 
  181 static u_int
  182 xdrmbuf_getpos(XDR *xdrs)
  183 {
  184         struct mbuf *m0 = (struct mbuf *) xdrs->x_base;
  185         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  186         u_int pos = 0;
  187 
  188         while (m0 && m0 != m) {
  189                 pos += m0->m_len;
  190                 m0 = m0->m_next;
  191         }
  192         KASSERT(m0, ("Corrupted mbuf chain"));
  193 
  194         return (pos + xdrs->x_handy);
  195 }
  196 
  197 static bool_t
  198 xdrmbuf_setpos(XDR *xdrs, u_int pos)
  199 {
  200         struct mbuf *m = (struct mbuf *) xdrs->x_base;
  201 
  202         while (m && pos > m->m_len) {
  203                 pos -= m->m_len;
  204                 m = m->m_next;
  205         }
  206         KASSERT(m, ("Corrupted mbuf chain"));
  207 
  208         xdrs->x_private = (void *) m;
  209         xdrs->x_handy = pos;
  210 
  211         return (TRUE);
  212 }
  213 
  214 static int32_t *
  215 xdrmbuf_inline(XDR *xdrs, u_int len)
  216 {
  217         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  218         size_t available;
  219         char *p;
  220 
  221         if (xdrs->x_op == XDR_ENCODE) {
  222                 available = M_TRAILINGSPACE(m) + (m->m_len - xdrs->x_handy);
  223         } else {
  224                 available = m->m_len - xdrs->x_handy;
  225         }
  226 
  227         if (available >= len) {
  228                 p = mtod(m, char *) + xdrs->x_handy;
  229                 if (((uintptr_t) p) & (sizeof(int32_t) - 1))
  230                         return (0);
  231                 xdrs->x_handy += len;
  232                 if (xdrs->x_handy > m->m_len)
  233                         m->m_len = xdrs->x_handy;
  234                 return ((int32_t *) p);
  235         }
  236 
  237         return (0);
  238 }

Cache object: a4f6bdae9fea6483ab05f49b43e430c5


[ 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.