inet_common.c revision ff550d0e264b51131fb34e9e83163b348d916640
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* or http://www.opensolaris.org/os/licensing.
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Minor number allocation for various protocol modules.
*/
#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/mutex.h>
#include <sys/ddi.h>
#include <sys/types.h>
#include <sys/mkdev.h>
#include <sys/param.h>
#include <inet/common.h>
typedef struct inet_arena {
vmem_t *ineta_arena; /* Minor number arena */
minor_t ineta_maxminor; /* max minor number in the arena */
} inet_arena_t;
/* Maximum minor number to use */
static minor_t inet_maxminor = INET_MAXMINOR;
void *
inet_minor_create(char *name, dev_t min_dev, int kmflags)
{
inet_arena_t *arena = kmem_alloc(sizeof (inet_arena_t), kmflags);
if (arena != NULL) {
arena->ineta_maxminor = MIN(MAXMIN32, inet_maxminor);
arena->ineta_arena = vmem_create(name,
(void *)min_dev, arena->ineta_maxminor - min_dev + 1,
1, NULL, NULL, NULL, 1, kmflags | VMC_IDENTIFIER);
if (arena->ineta_arena == NULL) {
kmem_free(arena, sizeof (inet_arena_t));
arena = NULL;
}
}
return (arena);
}
void
inet_minor_destroy(void *a)
{
inet_arena_t *arena = (inet_arena_t *)a;
if (arena != NULL) {
vmem_destroy(arena->ineta_arena);
kmem_free(arena, sizeof (inet_arena_t));
}
}
dev_t
inet_minor_alloc(void *a)
{
inet_arena_t *arena = (inet_arena_t *)a;
dev_t dev;
while ((dev = (dev_t)vmem_alloc(arena->ineta_arena, 1,
VM_NOSLEEP)) == 0) {
if (arena->ineta_maxminor >= inet_maxminor)
return (0);
if (vmem_add(arena->ineta_arena,
(void *)(uintptr_t)(arena->ineta_maxminor + 1),
inet_maxminor - arena->ineta_maxminor, VM_NOSLEEP) == NULL)
return (0);
arena->ineta_maxminor = inet_maxminor;
}
return (dev);
}
void
inet_minor_free(void *a, dev_t dev)
{
ASSERT((dev != OPENFAIL) && (dev != 0) && (dev <= inet_maxminor));
vmem_free(((inet_arena_t *)a)->ineta_arena, (void *)dev, 1);
}
/*
* This function is used to free a message that has gone through
* mi_copyin processing which modifies the M_IOCTL mblk's b_next
* and b_prev pointers. We use this function to set b_next/b_prev
* to NULL and free them.
*/
void
inet_freemsg(mblk_t *mp)
{
mblk_t *bp = mp;
for (; bp != NULL; bp = bp->b_cont) {
bp->b_prev = NULL;
bp->b_next = NULL;
}
freemsg(mp);
}