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/11.1/sys/xdr/xdr_mbuf.c 248318 2013-03-15 10:21:18Z glebius $");
   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         KASSERT(m != NULL, ("xdrmbuf_create with NULL mbuf chain"));
   69         xdrs->x_op = op;
   70         xdrs->x_ops = &xdrmbuf_ops;
   71         xdrs->x_base = (char *) m;
   72         if (op == XDR_ENCODE) {
   73                 m = m_last(m);
   74                 xdrs->x_private = m;
   75                 xdrs->x_handy = m->m_len;
   76         } else {
   77                 xdrs->x_private = m;
   78                 xdrs->x_handy = 0;
   79         }
   80 }
   81 
   82 void
   83 xdrmbuf_append(XDR *xdrs, struct mbuf *madd)
   84 {
   85         struct mbuf *m;
   86 
   87         KASSERT(xdrs->x_ops == &xdrmbuf_ops && xdrs->x_op == XDR_ENCODE,
   88             ("xdrmbuf_append: invalid XDR stream"));
   89 
   90         if (m_length(madd, NULL) == 0) {
   91                 m_freem(madd);
   92                 return;
   93         }
   94         
   95         m = (struct mbuf *) xdrs->x_private;
   96         m->m_next = madd;
   97 
   98         m = m_last(madd);
   99         xdrs->x_private = m;
  100         xdrs->x_handy = m->m_len;
  101 }
  102 
  103 struct mbuf *
  104 xdrmbuf_getall(XDR *xdrs)
  105 {
  106         struct mbuf *m0, *m;
  107 
  108         KASSERT(xdrs->x_ops == &xdrmbuf_ops && xdrs->x_op == XDR_DECODE,
  109             ("xdrmbuf_append: invalid XDR stream"));
  110 
  111         m0 = (struct mbuf *) xdrs->x_base;
  112         m = (struct mbuf *) xdrs->x_private;
  113         if (m0 != m) {
  114                 while (m0->m_next != m)
  115                         m0 = m0->m_next;
  116                 m0->m_next = NULL;
  117                 xdrs->x_private = NULL;
  118         } else {
  119                 xdrs->x_base = NULL;
  120                 xdrs->x_private = NULL;
  121         }
  122 
  123         if (m)
  124                 m_adj(m, xdrs->x_handy);
  125         else
  126                 m = m_get(M_WAITOK, MT_DATA);
  127         return (m);
  128 }
  129 
  130 static void
  131 xdrmbuf_destroy(XDR *xdrs)
  132 {
  133 
  134         if (xdrs->x_op == XDR_DECODE && xdrs->x_base) {
  135                 m_freem((struct mbuf *) xdrs->x_base);
  136                 xdrs->x_base = NULL;
  137                 xdrs->x_private = NULL;
  138         }
  139 }
  140 
  141 static bool_t
  142 xdrmbuf_getlong(XDR *xdrs, long *lp)
  143 {
  144         int32_t *p;
  145         int32_t t;
  146 
  147         p = xdrmbuf_inline(xdrs, sizeof(int32_t));
  148         if (p) {
  149                 t = *p;
  150         } else {
  151                 xdrmbuf_getbytes(xdrs, (char *) &t, sizeof(int32_t));
  152         }
  153 
  154         *lp = ntohl(t);
  155         return (TRUE);
  156 }
  157 
  158 static bool_t
  159 xdrmbuf_putlong(xdrs, lp)
  160         XDR *xdrs;
  161         const long *lp;
  162 {
  163         int32_t *p;
  164         int32_t t = htonl(*lp);
  165 
  166         p = xdrmbuf_inline(xdrs, sizeof(int32_t));
  167         if (p) {
  168                 *p = t;
  169                 return (TRUE);
  170         } else {
  171                 return (xdrmbuf_putbytes(xdrs, (char *) &t, sizeof(int32_t)));
  172         }
  173 }
  174 
  175 static bool_t
  176 xdrmbuf_getbytes(XDR *xdrs, char *addr, u_int len)
  177 {
  178         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  179         size_t sz;
  180 
  181         while (len > 0) {
  182                 /*
  183                  * Make sure we haven't hit the end.
  184                  */
  185                 if (!m) {
  186                         return (FALSE);
  187                 }
  188 
  189                 /*
  190                  * See how much we can get from this mbuf.
  191                  */
  192                 sz = m->m_len - xdrs->x_handy;
  193                 if (sz > len)
  194                         sz = len;
  195                 bcopy(mtod(m, const char *) + xdrs->x_handy, addr, sz);
  196 
  197                 addr += sz;
  198                 xdrs->x_handy += sz;
  199                 len -= sz;
  200 
  201                 if (xdrs->x_handy == m->m_len) {
  202                         m = m->m_next;
  203                         xdrs->x_private = (void *) m;
  204                         xdrs->x_handy = 0;
  205                 }
  206         }
  207         
  208         return (TRUE);
  209 }
  210 
  211 static bool_t
  212 xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len)
  213 {
  214         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  215         struct mbuf *n;
  216         size_t sz;
  217 
  218         while (len > 0) {
  219                 sz = M_TRAILINGSPACE(m) + (m->m_len - xdrs->x_handy);
  220                 if (sz > len)
  221                         sz = len;
  222                 bcopy(addr, mtod(m, char *) + xdrs->x_handy, sz);
  223                 addr += sz;
  224                 xdrs->x_handy += sz;
  225                 if (xdrs->x_handy > m->m_len)
  226                         m->m_len = xdrs->x_handy;
  227                 len -= sz;
  228 
  229                 if (xdrs->x_handy == m->m_len && M_TRAILINGSPACE(m) == 0) {
  230                         if (!m->m_next) {
  231                                 if (m->m_flags & M_EXT)
  232                                         n = m_getcl(M_WAITOK, m->m_type, 0);
  233                                 else
  234                                         n = m_get(M_WAITOK, m->m_type);
  235                                 m->m_next = n;
  236                         }
  237                         m = m->m_next;
  238                         xdrs->x_private = (void *) m;
  239                         xdrs->x_handy = 0;
  240                 }
  241         }
  242         
  243         return (TRUE);
  244 }
  245 
  246 static u_int
  247 xdrmbuf_getpos(XDR *xdrs)
  248 {
  249         struct mbuf *m0 = (struct mbuf *) xdrs->x_base;
  250         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  251         u_int pos = 0;
  252 
  253         while (m0 && m0 != m) {
  254                 pos += m0->m_len;
  255                 m0 = m0->m_next;
  256         }
  257         KASSERT(m0, ("Corrupted mbuf chain"));
  258 
  259         return (pos + xdrs->x_handy);
  260 }
  261 
  262 static bool_t
  263 xdrmbuf_setpos(XDR *xdrs, u_int pos)
  264 {
  265         struct mbuf *m = (struct mbuf *) xdrs->x_base;
  266 
  267         while (m && pos > m->m_len) {
  268                 pos -= m->m_len;
  269                 m = m->m_next;
  270         }
  271         KASSERT(m, ("Corrupted mbuf chain"));
  272 
  273         xdrs->x_private = (void *) m;
  274         xdrs->x_handy = pos;
  275 
  276         return (TRUE);
  277 }
  278 
  279 static int32_t *
  280 xdrmbuf_inline(XDR *xdrs, u_int len)
  281 {
  282         struct mbuf *m = (struct mbuf *) xdrs->x_private;
  283         size_t available;
  284         char *p;
  285 
  286         if (!m)
  287                 return (0);
  288         if (xdrs->x_op == XDR_ENCODE) {
  289                 available = M_TRAILINGSPACE(m) + (m->m_len - xdrs->x_handy);
  290         } else {
  291                 available = m->m_len - xdrs->x_handy;
  292         }
  293 
  294         if (available >= len) {
  295                 p = mtod(m, char *) + xdrs->x_handy;
  296                 if (((uintptr_t) p) & (sizeof(int32_t) - 1))
  297                         return (0);
  298                 xdrs->x_handy += len;
  299                 if (xdrs->x_handy > m->m_len)
  300                         m->m_len = xdrs->x_handy;
  301                 return ((int32_t *) p);
  302         }
  303 
  304         return (0);
  305 }

Cache object: 549898eeb07bc29f41202d090066cc40


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