Fix handling of ppp compressor modules, from Andrew Doran's input.
- ref count each compressor - allow {un,}registration of several modules at once - une RUN_ONCE to make sure the mutex is initialised, because unfortunately built-in (and bootloader-loaded) modules init functions are run before pseudo-devices attach (reported by Nick Hudson).
This commit is contained in:
parent
6a8d114c5f
commit
9f95a5d658
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bsd-comp.c,v 1.19 2008/11/25 02:40:36 cube Exp $ */
|
||||
/* $NetBSD: bsd-comp.c,v 1.20 2008/11/29 23:15:20 cube Exp $ */
|
||||
/* Id: bsd-comp.c,v 1.6 1996/08/28 06:31:58 paulus Exp */
|
||||
|
||||
/* Because this code is derived from the 4.3BSD compress source:
|
||||
|
@ -41,7 +41,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: bsd-comp.c,v 1.19 2008/11/25 02:40:36 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: bsd-comp.c,v 1.20 2008/11/29 23:15:20 cube Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -163,7 +163,6 @@ static struct compressor ppp_bsd_compress = {
|
|||
.decompress = bsd_decompress,
|
||||
.incomp = bsd_incomp,
|
||||
.decomp_stat = bsd_comp_stats,
|
||||
.comp_name = "ppp_bsdcomp"
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1099,9 +1098,9 @@ ppp_bsdcomp_modcmd(modcmd_t cmd, void *arg)
|
|||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
return ppp_register_compressor(&ppp_bsd_compress);
|
||||
return ppp_register_compressor(&ppp_bsd_compress, 1);
|
||||
case MODULE_CMD_FINI:
|
||||
return ppp_unregister_compressor(&ppp_bsd_compress);
|
||||
return ppp_unregister_compressor(&ppp_bsd_compress, 1);
|
||||
case MODULE_CMD_STAT:
|
||||
return 0;
|
||||
default:
|
||||
|
|
112
sys/net/if_ppp.c
112
sys/net/if_ppp.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ppp.c,v 1.125 2008/11/25 02:40:36 cube Exp $ */
|
||||
/* $NetBSD: if_ppp.c,v 1.126 2008/11/29 23:15:20 cube Exp $ */
|
||||
/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */
|
||||
|
||||
/*
|
||||
|
@ -102,7 +102,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.125 2008/11/25 02:40:36 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.126 2008/11/29 23:15:20 cube Exp $");
|
||||
|
||||
#include "ppp.h"
|
||||
|
||||
|
@ -126,6 +126,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.125 2008/11/25 02:40:36 cube Exp $");
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/once.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/intr.h>
|
||||
|
@ -216,10 +217,13 @@ struct if_clone ppp_cloner =
|
|||
static struct simplelock ppp_list_mutex = SIMPLELOCK_INITIALIZER;
|
||||
|
||||
#ifdef PPP_COMPRESS
|
||||
ONCE_DECL(ppp_compressor_mtx_init);
|
||||
static LIST_HEAD(, compressor) ppp_compressors = { NULL };
|
||||
static kmutex_t ppp_compressors_mtx;
|
||||
|
||||
static int ppp_compressor_init(void);
|
||||
static struct compressor *ppp_get_compressor(uint8_t);
|
||||
static void ppp_compressor_rele(struct compressor *);
|
||||
#endif /* PPP_COMPRESS */
|
||||
|
||||
|
||||
|
@ -235,7 +239,7 @@ pppattach(void)
|
|||
panic("pppattach");
|
||||
LIST_INIT(&ppp_softc_list);
|
||||
if_clone_attach(&ppp_cloner);
|
||||
mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
RUN_ONCE(&ppp_compressor_mtx_init, ppp_compressor_init);
|
||||
}
|
||||
|
||||
static struct ppp_softc *
|
||||
|
@ -601,7 +605,7 @@ pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag,
|
|||
s = splsoftnet();
|
||||
if (sc->sc_xc_state != NULL) {
|
||||
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
||||
module_rele(sc->sc_xcomp->comp_name);
|
||||
ppp_compressor_rele(sc->sc_xcomp);
|
||||
}
|
||||
sc->sc_xcomp = cp;
|
||||
sc->sc_xc_state = cp->comp_alloc(ccp_option, nb);
|
||||
|
@ -618,7 +622,7 @@ pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag,
|
|||
s = splsoftnet();
|
||||
if (sc->sc_rc_state != NULL) {
|
||||
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
||||
module_rele(sc->sc_rcomp->comp_name);
|
||||
ppp_compressor_rele(sc->sc_rcomp);
|
||||
}
|
||||
sc->sc_rcomp = cp;
|
||||
sc->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
|
||||
|
@ -1384,12 +1388,12 @@ ppp_ccp_closed(struct ppp_softc *sc)
|
|||
{
|
||||
if (sc->sc_xc_state) {
|
||||
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
||||
module_rele(sc->sc_xcomp->comp_name);
|
||||
ppp_compressor_rele(sc->sc_xcomp);
|
||||
sc->sc_xc_state = NULL;
|
||||
}
|
||||
if (sc->sc_rc_state) {
|
||||
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
||||
module_rele(sc->sc_rcomp->comp_name);
|
||||
ppp_compressor_rele(sc->sc_rcomp);
|
||||
sc->sc_rc_state = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1786,21 +1790,36 @@ static const struct ppp_known_compressor {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
ppp_compressor_init(void)
|
||||
{
|
||||
|
||||
mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_compressor_rele(struct compressor *cp)
|
||||
{
|
||||
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
--cp->comp_refcnt;
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
}
|
||||
|
||||
static struct compressor *
|
||||
ppp_get_compressor_noload(uint8_t ci, bool hold)
|
||||
{
|
||||
struct compressor *cp;
|
||||
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
KASSERT(mutex_owned(&ppp_compressors_mtx));
|
||||
LIST_FOREACH(cp, &ppp_compressors, comp_list) {
|
||||
if (cp->compress_proto == ci) {
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
if (hold && module_hold(cp->comp_name) != 0)
|
||||
return NULL;
|
||||
if (hold)
|
||||
++cp->comp_refcnt;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1808,48 +1827,75 @@ ppp_get_compressor_noload(uint8_t ci, bool hold)
|
|||
static struct compressor *
|
||||
ppp_get_compressor(uint8_t ci)
|
||||
{
|
||||
struct compressor *cp;
|
||||
struct compressor *cp = NULL;
|
||||
const struct ppp_known_compressor *pkc;
|
||||
|
||||
if ((cp = ppp_get_compressor_noload(ci, true)) != NULL)
|
||||
return cp;
|
||||
|
||||
/* Not found, so try to autoload a module */
|
||||
for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) {
|
||||
if (pkc->code == ci) {
|
||||
if (module_autoload(pkc->module, MODULE_CLASS_MISC))
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
cp = ppp_get_compressor_noload(ci, true);
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
if (cp == NULL) {
|
||||
/* Not found, so try to autoload a module */
|
||||
for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) {
|
||||
if (pkc->code == ci) {
|
||||
if (module_autoload(pkc->module,
|
||||
MODULE_CLASS_MISC) != 0)
|
||||
break;
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
cp = ppp_get_compressor_noload(ci, true);
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
break;
|
||||
return ppp_get_compressor_noload(ci, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return cp;
|
||||
}
|
||||
|
||||
int
|
||||
ppp_register_compressor(struct compressor *pc)
|
||||
ppp_register_compressor(struct compressor *pc, size_t ncomp)
|
||||
{
|
||||
int error = 0;
|
||||
size_t i;
|
||||
|
||||
if (ppp_get_compressor_noload(pc->compress_proto, false) != NULL)
|
||||
return EEXIST;
|
||||
RUN_ONCE(&ppp_compressor_mtx_init, ppp_compressor_init);
|
||||
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
LIST_INSERT_HEAD(&ppp_compressors, pc, comp_list);
|
||||
for (i = 0; i < ncomp; i++) {
|
||||
if (ppp_get_compressor_noload(pc[i].compress_proto,
|
||||
false) != NULL)
|
||||
error = EEXIST;
|
||||
}
|
||||
if (!error) {
|
||||
for (i = 0; i < ncomp; i++) {
|
||||
pc[i].comp_refcnt = 0;
|
||||
LIST_INSERT_HEAD(&ppp_compressors, &pc[i], comp_list);
|
||||
}
|
||||
}
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
ppp_unregister_compressor(struct compressor *pc)
|
||||
ppp_unregister_compressor(struct compressor *pc, size_t ncomp)
|
||||
{
|
||||
|
||||
if (ppp_get_compressor_noload(pc->compress_proto, false) != pc)
|
||||
return ENOENT;
|
||||
int error = 0;
|
||||
size_t i;
|
||||
|
||||
mutex_enter(&ppp_compressors_mtx);
|
||||
LIST_REMOVE(pc, comp_list);
|
||||
for (i = 0; i < ncomp; i++) {
|
||||
if (ppp_get_compressor_noload(pc[i].compress_proto,
|
||||
false) != &pc[i])
|
||||
error = ENOENT;
|
||||
else if (pc[i].comp_refcnt != 0)
|
||||
error = EBUSY;
|
||||
}
|
||||
if (!error) {
|
||||
for (i = 0; i < ncomp; i++) {
|
||||
LIST_REMOVE(&pc[i], comp_list);
|
||||
}
|
||||
}
|
||||
mutex_exit(&ppp_compressors_mtx);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ppp.h,v 1.24 2008/11/25 02:40:36 cube Exp $ */
|
||||
/* $NetBSD: if_ppp.h,v 1.25 2008/11/29 23:15:20 cube Exp $ */
|
||||
/* Id: if_ppp.h,v 1.16 1997/04/30 05:46:04 paulus Exp */
|
||||
|
||||
/*
|
||||
|
@ -175,7 +175,7 @@ struct ppp_rawin {
|
|||
void pppattach(void);
|
||||
|
||||
struct compressor;
|
||||
int ppp_register_compressor(struct compressor *);
|
||||
int ppp_unregister_compressor(struct compressor *);
|
||||
int ppp_register_compressor(struct compressor *, size_t);
|
||||
int ppp_unregister_compressor(struct compressor *, size_t);
|
||||
#endif
|
||||
#endif /* !_NET_IF_PPP_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ppp-comp.h,v 1.15 2008/11/25 02:40:36 cube Exp $ */
|
||||
/* $NetBSD: ppp-comp.h,v 1.16 2008/11/29 23:15:20 cube Exp $ */
|
||||
|
||||
/*
|
||||
* ppp-comp.h - Definitions for doing PPP packet compression.
|
||||
|
@ -96,7 +96,7 @@ struct compressor {
|
|||
void (*decomp_stat)(void *, struct compstat *);
|
||||
|
||||
LIST_ENTRY(compressor) comp_list;
|
||||
const char *comp_name;
|
||||
unsigned int comp_refcnt;
|
||||
};
|
||||
#endif /* PACKETPTR */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ppp-deflate.c,v 1.18 2008/11/25 02:40:36 cube Exp $ */
|
||||
/* $NetBSD: ppp-deflate.c,v 1.19 2008/11/29 23:15:20 cube Exp $ */
|
||||
/* Id: ppp-deflate.c,v 1.5 1997/03/04 03:33:28 paulus Exp */
|
||||
|
||||
/*
|
||||
|
@ -39,7 +39,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ppp-deflate.c,v 1.18 2008/11/25 02:40:36 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ppp-deflate.c,v 1.19 2008/11/29 23:15:20 cube Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -95,7 +95,7 @@ static void z_comp_stats(void *state, struct compstat *stats);
|
|||
/*
|
||||
* Procedures exported to if_ppp.c.
|
||||
*/
|
||||
static struct compressor ppp_deflate = {
|
||||
static struct compressor ppp_deflate[2] = { {
|
||||
.compress_proto = CI_DEFLATE,
|
||||
.comp_alloc = z_comp_alloc,
|
||||
.comp_free = z_comp_free,
|
||||
|
@ -110,10 +110,8 @@ static struct compressor ppp_deflate = {
|
|||
.decompress = z_decompress,
|
||||
.incomp = z_incomp,
|
||||
.decomp_stat = z_comp_stats,
|
||||
.comp_name = "ppp_deflate"
|
||||
};
|
||||
|
||||
static struct compressor ppp_deflate_draft = {
|
||||
},
|
||||
{
|
||||
.compress_proto = CI_DEFLATE_DRAFT,
|
||||
.comp_alloc = z_comp_alloc,
|
||||
.comp_free = z_comp_free,
|
||||
|
@ -128,8 +126,7 @@ static struct compressor ppp_deflate_draft = {
|
|||
.decompress = z_decompress,
|
||||
.incomp = z_incomp,
|
||||
.decomp_stat = z_comp_stats,
|
||||
.comp_name = "ppp_deflate"
|
||||
};
|
||||
} };
|
||||
/*
|
||||
* Space allocation and freeing routines for use by zlib routines.
|
||||
*/
|
||||
|
@ -674,22 +671,12 @@ MODULE(MODULE_CLASS_MISC, ppp_deflate, NULL);
|
|||
static int
|
||||
ppp_deflate_modcmd(modcmd_t cmd, void *arg)
|
||||
{
|
||||
int error, error1;
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
if ((error = ppp_register_compressor(&ppp_deflate)) != 0)
|
||||
return error;
|
||||
if ((error =
|
||||
ppp_register_compressor(&ppp_deflate_draft)) != 0)
|
||||
(void)ppp_unregister_compressor(&ppp_deflate);
|
||||
return error;
|
||||
return ppp_register_compressor(ppp_deflate, 2);
|
||||
case MODULE_CMD_FINI:
|
||||
error = ppp_unregister_compressor(&ppp_deflate);
|
||||
error1 = ppp_unregister_compressor(&ppp_deflate_draft);
|
||||
if (error)
|
||||
return error;
|
||||
return error1;
|
||||
return ppp_unregister_compressor(ppp_deflate, 2);
|
||||
case MODULE_CMD_STAT:
|
||||
return 0;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue