From 5c7f6dfe4e716409ffc46b8f8d7880e174d6eb02 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 30 Nov 2002 00:49:43 +0000 Subject: devd kernel improvements: 1) Record all device events when devctl is enabled, rather than just when devd has devctl open. This is necessary to prevent races between when a device arrives, and when devd starts. 2) Add hw.bus.devctl_disable to disable devctl, this can also be set as a tunable. 3) Fix async support. Reset nonblocking and async_td in open. remove async flags. 4) Free all memory when devctl is disabled. Approved by: re (blanket) --- sys/kern/subr_bus.c | 59 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 21 deletions(-) (limited to 'sys/kern/subr_bus.c') diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 4791f4c..20262cd 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -54,6 +54,8 @@ #include +SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL); + /* * Used to attach drivers to devclasses. */ @@ -200,6 +202,13 @@ void print_devclass_list(void); * tested since 3.4 or 2.2.8! */ +static int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS); +static int devctl_disable = 0; +TUNABLE_INT("hw.bus.devctl_disable", &devctl_disable); +SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable, + CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_devctl_disable, + "I", "devctl disable"); + static d_open_t devopen; static d_close_t devclose; static d_read_t devread; @@ -235,7 +244,6 @@ struct dev_softc { int inuse; int nonblock; - int async; struct mtx mtx; struct cv cv; struct selinfo sel; @@ -261,27 +269,17 @@ devopen(dev_t dev, int oflags, int devtype, d_thread_t *td) return (EBUSY); /* move to init */ devsoftc.inuse = 1; + devsoftc.nonblock = 0; + devsoftc.async_td = NULL; return (0); } static int devclose(dev_t dev, int fflag, int devtype, d_thread_t *td) { - struct dev_event_info *n1; - devsoftc.inuse = 0; mtx_lock(&devsoftc.mtx); cv_broadcast(&devsoftc.cv); - /* - * See note in devread. If we deside to keep data until read, then - * remove the following while loop. XXX - */ - while (!TAILQ_EMPTY(&devsoftc.devq)) { - n1 = TAILQ_FIRST(&devsoftc.devq); - TAILQ_REMOVE(&devsoftc.devq, n1, dei_link); - free(n1->dei_data, M_BUS); - free(n1, M_BUS); - } mtx_unlock(&devsoftc.mtx); return (0); @@ -337,14 +335,10 @@ devioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td) devsoftc.nonblock = 0; return (0); case FIOASYNC: - if (*(int*)data) { - devsoftc.async = 1; + if (*(int*)data) devsoftc.async_td = td; - } - else { - devsoftc.async = 0; + else devsoftc.async_td = NULL; - } return (0); /* (un)Support for other fcntl() calls. */ @@ -408,7 +402,7 @@ devaddq(const char *type, const char *what, device_t dev) char *loc; const char *parstr; - if (!devsoftc.inuse) + if (devctl_disable) return; n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT); if (n1 == NULL) @@ -487,6 +481,30 @@ devnomatch(device_t dev) return; } +static int +sysctl_devctl_disable(SYSCTL_HANDLER_ARGS) +{ + struct dev_event_info *n1; + int dis, error; + + dis = devctl_disable; + error = sysctl_handle_int(oidp, &dis, 0, req); + if (error || !req->newptr) + return (error); + mtx_lock(&devsoftc.mtx); + devctl_disable = dis; + if (dis) { + while (!TAILQ_EMPTY(&devsoftc.devq)) { + n1 = TAILQ_FIRST(&devsoftc.devq); + TAILQ_REMOVE(&devsoftc.devq, n1, dei_link); + free(n1->dei_data, M_BUS); + free(n1, M_BUS); + } + } + mtx_unlock(&devsoftc.mtx); + return (0); +} + /* End of /dev/devctl code */ TAILQ_HEAD(,device) bus_data_devices; @@ -2458,7 +2476,6 @@ print_devclass_list(void) * We might like to add the ability to scan devclasses and/or drivers to * determine what else is currently loaded/available. */ -SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL); static int sysctl_bus(SYSCTL_HANDLER_ARGS) -- cgit v1.1