mirror of
https://github.com/opnsense/src.git
synced 2026-04-23 07:07:24 -04:00
Implement an utility function that can be used by device drivers to
implement the ATMIOCGVCCS ioctls. This routine handles changing VCC tables (which can occure because we cannot hold the driver mutex while allocating memory) with a loop and a re-allocation, should the table not fit in the allocated memory.
This commit is contained in:
parent
198b0c39a9
commit
09d405d969
2 changed files with 59 additions and 0 deletions
|
|
@ -268,4 +268,6 @@ void atm_input(struct ifnet *, struct atm_pseudohdr *,
|
|||
struct mbuf *, void *);
|
||||
int atm_output(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *);
|
||||
struct atmio_vcctable *atm_getvccs(struct atmio_vcc **, u_int, u_int,
|
||||
struct mtx *, int);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/sockio.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/netisr.h>
|
||||
|
|
@ -404,6 +405,62 @@ atm_ifdetach(struct ifnet *ifp)
|
|||
if_detach(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support routine for the SIOCATMGVCCS ioctl().
|
||||
*
|
||||
* This routine assumes, that the private VCC structures used by the driver
|
||||
* begin with a struct atmio_vcc.
|
||||
*
|
||||
* Return a table of VCCs in a freshly allocated memory area.
|
||||
* Here we have a problem: we first count, how many vccs we need
|
||||
* to return. The we allocate the memory and finally fill it in.
|
||||
* Because we cannot lock while calling malloc, the number of active
|
||||
* vccs may change while we're in malloc. So we allocate a couple of
|
||||
* vccs more and if space anyway is not enough re-iterate.
|
||||
*
|
||||
* We could use an sx lock for the vcc tables.
|
||||
*/
|
||||
struct atmio_vcctable *
|
||||
atm_getvccs(struct atmio_vcc **table, u_int size, u_int start,
|
||||
struct mtx *lock, int waitok)
|
||||
{
|
||||
u_int cid, alloc;
|
||||
size_t len;
|
||||
struct atmio_vcctable *vccs;
|
||||
struct atmio_vcc *v;
|
||||
|
||||
alloc = start + 10;
|
||||
vccs = NULL;
|
||||
|
||||
for (;;) {
|
||||
len = sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]);
|
||||
vccs = reallocf(vccs, len, M_TEMP,
|
||||
waitok ? M_WAITOK : M_NOWAIT);
|
||||
if (vccs == NULL)
|
||||
return (NULL);
|
||||
bzero(vccs, len);
|
||||
|
||||
vccs->count = 0;
|
||||
v = vccs->vccs;
|
||||
|
||||
mtx_lock(lock);
|
||||
for (cid = 0; cid < size; cid++)
|
||||
if (table[cid] != NULL) {
|
||||
if (++vccs->count == alloc)
|
||||
/* too many - try again */
|
||||
break;
|
||||
*v++ = *table[cid];
|
||||
}
|
||||
mtx_unlock(lock);
|
||||
|
||||
if (cid == size)
|
||||
break;
|
||||
|
||||
alloc *= 2;
|
||||
}
|
||||
return (vccs);
|
||||
}
|
||||
|
||||
static moduledata_t atm_mod = {
|
||||
"atm",
|
||||
NULL,
|
||||
|
|
|
|||
Loading…
Reference in a new issue