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:
cube 2008-11-29 23:15:20 +00:00
parent 6a8d114c5f
commit 9f95a5d658
5 changed files with 96 additions and 64 deletions

View File

@ -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:

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 */

View File

@ -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: