xdr_mblk.c revision cf98b944cdc2063fc14f3fd525e284de3ed29fd0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
/*
* xdr_mblk.c, XDR implementation on kernel streams mblks.
*/
#include <sys/sysmacros.h>
static void xdrmblk_destroy(XDR *);
static mblk_t *xdrmblk_alloc(int);
static void xdrmblk_skip_fully_read_mblks(XDR *);
/*
* Xdr on mblks operations vector.
*/
struct xdr_ops xdrmblk_ops = {
};
/*
* The xdrmblk_params structure holds the internal data for the XDR stream.
* The x_private member of the XDR points to this structure. The
* xdrmblk_params structure is dynamically allocated in xdrmblk_init() and
* freed in xdrmblk_destroy().
*
* The apos and rpos members of the xdrmblk_params structure are used to
* implement xdrmblk_getpos() and xdrmblk_setpos().
*
* In addition to the xdrmblk_params structure we store some additional
* internal data directly in the XDR stream structure:
*
* x_base A pointer to the current mblk (that one we are currently
* working with).
* x_handy The number of available bytes (either for read or for write) in
* the current mblk.
*/
struct xdrmblk_params {
int sz;
};
/*
* Initialize xdr stream.
*/
void
{
struct xdrmblk_params *p;
p->apos = 0;
p->rpos = 0;
if (op == XDR_DECODE) {
} else {
}
}
static void
{
}
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
/* LINTED pointer alignment */
if (m == NULL)
return (FALSE);
/*
* If the pointer is not aligned or there is not
* enough bytes, pullupmsg to get enough bytes and
* align the mblk.
*/
/*
* Could have failed due to not
* enough data or an allocb failure.
*/
return (FALSE);
}
p->rpos = 0;
}
/* LINTED pointer alignment */
return (TRUE);
}
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
/* LINTED pointer alignment */
if (m == NULL)
return (FALSE);
}
m = m->b_cont;
p->rpos = 0;
if (m == NULL) {
return (FALSE);
}
}
/* LINTED pointer alignment */
return (TRUE);
}
/*
* We pick 16 as a compromise threshold for most architectures.
*/
#define XDRMBLK_BCOPY_LIMIT 16
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
int i;
/* LINTED pointer alignment */
if (m == NULL)
return (FALSE);
/*
* Performance tweak: converted explicit bcopy()
* call to simple in-line. This function is called
* to process things like readdir reply filenames
* which are small strings--typically 12 bytes or less.
* Overhead of calling bcopy() is obnoxious for such
* small copies.
*/
} else {
}
}
m = m->b_cont;
p->rpos = 0;
if (m == NULL) {
return (FALSE);
}
}
if (len < XDRMBLK_BCOPY_LIMIT) {
for (i = 0; i < len; i++)
} else {
}
return (TRUE);
}
/*
* Sort of like getbytes except that instead of getting bytes we return the
* mblk chain which contains the data. If the data ends in the middle of
* an mblk, the mblk is dup'd and split, so that the data will end on an
* mblk. Note that it is up to the caller to keep track of the data length
* and not walk too far down the mblk chain.
*/
{
struct xdrmblk_params *p;
int len;
return (FALSE);
/* LINTED pointer alignment */
*mm = m;
/*
* Walk the mblk chain until we get to the end or we've gathered
* enough data.
*/
len = 0;
m = m->b_cont;
}
if (m == NULL) {
return (FALSE);
} else {
/*
* Split the mblk with the last chunk of data and
* insert it into the chain. The new mblk goes
* after the existing one so that it will get freed
* properly.
*/
return (FALSE);
m = nextm; /* for x_base */
}
}
p->rpos = 0;
return (TRUE);
}
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
int i;
/* LINTED pointer alignment */
if (m == NULL)
return (FALSE);
/*
* Performance tweak: converted explicit bcopy()
* call to simple in-line. This function is called
* to process things like readdir reply filenames
* which are small strings--typically 12 bytes or less.
* Overhead of calling bcopy() is obnoxious for such
* small copies.
*/
} else {
}
}
/*
* We don't have enough space, so allocate the
* amount we need, or sz, whichever is larger.
* It is better to let the underlying transport divide
* large chunks than to try and guess what is best.
*/
m = m->b_cont;
p->rpos = 0;
if (m == NULL) {
return (FALSE);
}
}
if (len < XDRMBLK_BCOPY_LIMIT) {
for (i = 0; i < len; i++)
} else {
}
return (TRUE);
}
/*
* We avoid a copy by merely adding this mblk to the list. The caller is
* responsible for allocating and filling in the mblk. If len is
* not a multiple of BYTES_PER_XDR_UNIT, the caller has the option
* of making the data a BYTES_PER_XDR_UNIT multiple (b_wptr - b_rptr is
* a BYTES_PER_XDR_UNIT multiple), but in this case the caller has to ensure
* that the filler bytes are initialized to zero.
*/
{
struct xdrmblk_params *p;
if ((DLEN(m) % BYTES_PER_XDR_UNIT) != 0)
return (FALSE);
return (FALSE);
/* LINTED pointer alignment */
/* base points to the last mblk */
while (m->b_cont) {
m = m->b_cont;
}
return (TRUE);
}
static uint_t
{
}
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
return (FALSE);
return (FALSE);
return (TRUE);
/* LINTED pointer alignment */
else
return (TRUE);
}
#ifdef DEBUG
static int xdrmblk_inline_hits = 0;
static int xdrmblk_inline_misses = 0;
static int do_xdrmblk_inline = 1;
#endif
static rpc_inline_t *
{
mblk_t *m;
unsigned char **mptr;
struct xdrmblk_params *p;
/*
* Can't inline XDR_FREE calls, doesn't make sense.
*/
return (NULL);
#ifdef DEBUG
if (!do_xdrmblk_inline) {
return (NULL);
}
#endif
/*
* Can't inline if there isn't enough room.
*/
#ifdef DEBUG
#endif
return (NULL);
}
/* LINTED pointer alignment */
/* LINTED pointer alignment */
} else {
/* LINTED pointer alignment */
}
/*
* Can't inline if the buffer is not 4 byte aligned, or if there is
* more than one reference to the data block associated with this mblk.
* This last check is used because the caller may want to modify the
* data in the inlined portion and someone else is holding a reference
* to the data who may not want it to be modified.
*/
#ifdef DEBUG
#endif
return (NULL);
}
#ifdef DEBUG
#endif
return (buf);
}
static bool_t
{
mblk_t *m;
struct xdrmblk_params *p;
int len;
switch (request) {
case XDR_PEEK:
/*
* Return the next 4 byte unit in the XDR stream.
*/
return (FALSE);
/* LINTED pointer alignment */
/*
* If the pointer is not aligned, fail the peek
*/
return (FALSE);
/* LINTED pointer alignment */
return (TRUE);
case XDR_SKIPBYTES:
if (len < 0)
return (FALSE);
if (len == 0)
return (TRUE);
/* LINTED pointer alignment */
if (m == NULL)
return (FALSE);
}
m = m->b_cont;
p->rpos = 0;
if (m == NULL) {
return (FALSE);
}
}
return (TRUE);
default:
return (FALSE);
}
}
#define HDR_SPACE 128
static mblk_t *
xdrmblk_alloc(int sz)
{
if (sz == 0)
return (NULL);
/*
* Pad the front of the message to allow the lower networking
* layers space to add headers as needed.
*/
return (NULL);
}
return (mp);
}
/*
* Skip fully read or empty mblks
*/
static void
{
mblk_t *m;
struct xdrmblk_params *p;
return;
/* LINTED pointer alignment */
if (m == NULL)
return;
p->rpos = 0;
do {
m = m->b_cont;
if (m == NULL)
break;
}