o Use subr_unit allocator. This simplifies code much:

- Remove get_free_unit().
  - Remove SLIST of nodes.
  - Remove global mutex.

o Increase NGD_MAX to 999.
o Move ngd_mod_event() up to netgraph methods.
This commit is contained in:
Gleb Smirnoff 2005-03-14 16:02:53 +00:00
parent de52d21a02
commit 5cdd064d8a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=143593

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2002 Mark Santcroos <marks@ripe.net>
* Copyright (c) 2004 Gleb Smirnoff <glebius@FreeBSD.org>
* Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -88,7 +88,6 @@ NETGRAPH_INIT(device, &ngd_typestruct);
/* per node data */
struct ngd_private {
struct ifqueue readq;
SLIST_ENTRY(ngd_private) links;
struct ng_node *node;
struct ng_hook *hook;
struct cdev *ngddev;
@ -100,12 +99,11 @@ struct ngd_private {
};
typedef struct ngd_private *priv_p;
/* List of all active nodes and mutex to protect it */
static SLIST_HEAD(, ngd_private) ngd_nodes = SLIST_HEAD_INITIALIZER(ngd_nodes);
static struct mtx ng_device_mtx;
/* unit number allocator entity */
static struct unrhdr *ngd_unit;
/* Maximum number of NGD devices */
#define MAX_NGD 25 /* should be more than enough for now */
#define MAX_NGD 999
static d_close_t ngdclose;
static d_open_t ngdopen;
@ -129,13 +127,32 @@ static struct cdevsw ngd_cdevsw = {
.d_name = NG_DEVICE_DEVNAME,
};
/* Helper functions */
static int get_free_unit(void);
/******************************************************************************
* Netgraph methods
******************************************************************************/
/*
* Handle loading and unloading for this node type.
*/
static int
ng_device_mod_event(module_t mod, int event, void *data)
{
int error = 0;
switch (event) {
case MOD_LOAD:
ngd_unit = new_unrhdr(0, MAX_NGD, NULL);
break;
case MOD_UNLOAD:
delete_unrhdr(ngd_unit);
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
/*
* create new node
*/
@ -150,17 +167,8 @@ ng_device_constructor(node_p node)
if (priv == NULL)
return (ENOMEM);
mtx_lock(&ng_device_mtx);
priv->unit = get_free_unit();
if(priv->unit < 0) {
printf("%s: No free unit found by get_free_unit(), "
"increase MAX_NGD\n",__func__);
mtx_unlock(&ng_device_mtx);
FREE(priv, M_NETGRAPH);
return(EINVAL);
}
SLIST_INSERT_HEAD(&ngd_nodes, priv, links);
mtx_unlock(&ng_device_mtx);
/* Allocate unit number */
priv->unit = alloc_unr(ngd_unit);
/* Initialize mutexes and queue */
mtx_init(&priv->ngd_mtx, "ng_device", NULL, MTX_DEF);
@ -177,6 +185,7 @@ ng_device_constructor(node_p node)
printf("%s(): make_dev() failed\n",__func__);
mtx_destroy(&priv->ngd_mtx);
mtx_destroy(&priv->readq.ifq_mtx);
free_unr(ngd_unit, priv->unit);
FREE(priv, M_NETGRAPH);
return(EINVAL);
}
@ -203,9 +212,9 @@ ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook)
if (msg->header.typecookie == NGM_DEVICE_COOKIE) {
switch (msg->header.cmd) {
case NGM_DEVICE_GET_DEVNAME:
/* XXX: Fix when NGD_MAX us bigger */
/* XXX: Fix when MAX_NGD us bigger */
NG_MKRESPONSE(resp, msg,
strlen(NG_DEVICE_DEVNAME) + 3, M_NOWAIT);
strlen(NG_DEVICE_DEVNAME) + 4, M_NOWAIT);
if (resp == NULL)
ERROUT(ENOMEM);
@ -293,13 +302,11 @@ ng_device_disconnect(hook_p hook)
destroy_dev(priv->ngddev);
mtx_destroy(&priv->ngd_mtx);
mtx_lock(&ng_device_mtx);
SLIST_REMOVE(&ngd_nodes, priv, ngd_private, links);
mtx_unlock(&ng_device_mtx);
IF_DRAIN(&priv->readq);
mtx_destroy(&(priv)->readq.ifq_mtx);
free_unr(ngd_unit, priv->unit);
FREE(priv, M_NETGRAPH);
ng_rmnode_self(NG_HOOK_NODE(hook));
@ -376,16 +383,6 @@ ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
DBG;
SLIST_FOREACH(tmp,&sc->head,links) {
if(tmp->ngddev == dev) {
connection = tmp;
}
}
if(connection == NULL) {
printf("%s(): connection is still NULL, no dev found\n",__func__);
return(-1);
}
NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s),
M_NOWAIT);
if (msg == NULL) {
@ -493,62 +490,3 @@ ngdpoll(struct cdev *dev, int events, struct thread *td)
return (revents);
}
/******************************************************************************
* Helper subroutines
******************************************************************************/
static int
get_free_unit()
{
struct ngd_private *priv = NULL;
int n = 0;
int unit = -1;
DBG;
mtx_assert(&ng_device_mtx, MA_OWNED);
/* When there is no list yet, the first device unit is always 0. */
if SLIST_EMPTY(&ngd_nodes)
return(0);
/* Just do a brute force loop to find the first free unit that is
* smaller than MAX_NGD.
* Set MAX_NGD to a large value, doesn't impact performance.
*/
for(n = 0; n<MAX_NGD && unit == -1; n++) {
SLIST_FOREACH(priv, &ngd_nodes, links) {
if(priv->unit == n) {
unit = -1;
break;
}
unit = n;
}
}
return (unit);
}
/*
* Handle loading and unloading for this node type.
*/
static int
ng_device_mod_event(module_t mod, int event, void *data)
{
int error = 0;
switch (event) {
case MOD_LOAD:
mtx_init(&ng_device_mtx, "ng_device global", NULL, MTX_DEF);
break;
case MOD_UNLOAD:
mtx_destroy(&ng_device_mtx);
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}