diff options
author | kib <kib@FreeBSD.org> | 2007-07-03 18:18:30 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-07-03 18:18:30 +0000 |
commit | c88cac4c418f97044c4063d61485f404a44d14e7 (patch) | |
tree | bdca5081d32c975c0dfa338ba3fbf619942270c5 | |
parent | a5a2c7551bc228c50a49d223e031e75a2a1dff2b (diff) | |
download | FreeBSD-src-c88cac4c418f97044c4063d61485f404a44d14e7.zip FreeBSD-src-c88cac4c418f97044c4063d61485f404a44d14e7.tar.gz |
Rev. 1.204 and 1.205 got an erronous version of destroy_dev() that
calls destroy_dev_sched() with cdev mutex locked. Commit the code
that was actually tested.
Pointy hat to: kib
Approved by: re (implicit)
-rw-r--r-- | sys/kern/kern_conf.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index dba041f..20d3bc3 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -52,7 +52,8 @@ static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage"); struct mtx devmtx; static void destroy_devl(struct cdev *dev); - +static int destroy_dev_sched_cbl(struct cdev *dev, + void (*cb)(void *), void *arg); static struct cdev *make_dev_credv(int flags, struct cdevsw *devsw, int minornr, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, @@ -788,7 +789,7 @@ destroy_dev(struct cdev *dev) destroy_devl(dev); dev_unlock_and_free(); } else - destroy_dev_sched(dev); + destroy_dev_sched_cbl(dev, NULL, NULL); } const char * @@ -1014,13 +1015,17 @@ destroy_dev_tq(void *ctx, int pending) dev_unlock(); } -int -destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg) +/* + * devmtx shall be locked on entry. devmtx will be unlocked after + * function return. + */ +static int +destroy_dev_sched_cbl(struct cdev *dev, void (*cb)(void *), void *arg) { struct cdev_priv *cp; - + + mtx_assert(&devmtx, MA_OWNED); cp = dev->si_priv; - dev_lock(); if (cp->cdp_flags & CDP_SCHED_DTR) { dev_unlock(); return (0); @@ -1036,6 +1041,13 @@ destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg) } int +destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg) +{ + dev_lock(); + return (destroy_dev_sched_cbl(dev, cb, arg)); +} + +int destroy_dev_sched(struct cdev *dev) { return (destroy_dev_sched_cb(dev, NULL, NULL)); |