Module Name: src Committed By: pgoyette Date: Wed Jul 20 06:51:13 UTC 2016
Modified Files: src/sys/dev [pgoyette-localcount]: cgd.c Log Message: First pass at updating the cgd(4) driver for use with localcount(9) ref-counts. So far all I've done is to manage the ref-counts. This will defer removal of the driver from the devsw tables and/or the autoconf tree while anyone has a reference to any of the device's critical data (mostly, the softc or the device_t). Note that these ref-counts will only defer the removal; once the references are released, the removal will proceed. On-going work is needed to identify potentially blocking operations, and to deny any removals if such operations are in-flight. We really shouldn't be waiting (possibly indefinitely) for these operations to complete, especially since removals could be attempted by the module(9) subsystem while holding the kernel_config lock. To generate a diff of this commit: cvs rdiff -u -r1.108.2.3 -r1.108.2.4 src/sys/dev/cgd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/cgd.c diff -u src/sys/dev/cgd.c:1.108.2.3 src/sys/dev/cgd.c:1.108.2.4 --- src/sys/dev/cgd.c:1.108.2.3 Wed Jul 20 04:33:53 2016 +++ src/sys/dev/cgd.c Wed Jul 20 06:51:13 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: cgd.c,v 1.108.2.3 2016/07/20 04:33:53 pgoyette Exp $ */ +/* $NetBSD: cgd.c,v 1.108.2.4 2016/07/20 06:51:13 pgoyette Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.108.2.3 2016/07/20 04:33:53 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.108.2.4 2016/07/20 06:51:13 pgoyette Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -176,6 +176,17 @@ static void hexprint(const char *, void /* The code */ +static void +cgd_release(dev_t dev) +{ + int unit = CGDUNIT(dev); + device_t self; + + self = device_lookup_acquire(&cgd_cd, unit); + if (self != NULL) + device_release(self); +} + static struct cgd_softc * getcgd_softc(dev_t dev) { @@ -247,6 +258,7 @@ cgdattach(int num) static struct cgd_softc * cgd_spawn(int unit) { + device_t self; cfdata_t cf; cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); @@ -255,7 +267,17 @@ cgd_spawn(int unit) cf->cf_unit = unit; cf->cf_fstate = FSTATE_STAR; - return device_private(config_attach_pseudo(cf)); + if (config_attach_pseudo(cf) == NULL) + return NULL; + + self = device_lookup_acquire(&cgd_cd, unit); + if (self == NULL) + return NULL; + else + /* + * Note that we return with a reference to the device! + */ + return device_private(self); } static int @@ -326,23 +348,30 @@ cgdstrategy(struct buf *bp) bp->b_error = EINVAL; bp->b_resid = bp->b_bcount; biodone(bp); + cgd_release(bp->b_dev); return; } /* XXXrcd: Should we test for (cs != NULL)? */ dk_strategy(&cs->sc_dksc, bp); + cgd_release(bp->b_dev); return; } static int cgdsize(dev_t dev) { + int retval; struct cgd_softc *cs = getcgd_softc(dev); DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev)); if (!cs) - return -1; - return dk_size(&cs->sc_dksc, dev); + retval = -1; + else + retval = dk_size(&cs->sc_dksc, dev); + + cgd_release(dev); + return retval; } /* @@ -451,6 +480,7 @@ cgd_diskstart(device_t dev, struct buf * static void cgdiodone(struct buf *nbp) { + dev_t dev; struct buf *obp = nbp->b_private; struct cgd_softc *cs = getcgd_softc(obp->b_dev); struct dk_softc *dksc = &cs->sc_dksc; @@ -494,7 +524,14 @@ cgdiodone(struct buf *nbp) if (obp->b_error != 0) obp->b_resid = obp->b_bcount; + /* + * copy the dev_t, finish the disk operation, and release the + * reference we're holding on to (from cgd_getsoftc() earlier) + */ + dev = obp->b_dev; dk_done(dksc, obp); + cgd_release(dev); + dk_start(dksc, NULL); } @@ -817,8 +854,10 @@ cgd_ioctl_get(dev_t dev, void *data, str if (cgu->cgu_unit == -1) cgu->cgu_unit = unit; - if (cgu->cgu_unit < 0) + if (cgu->cgu_unit < 0) { + cgd_release(dev); return EINVAL; /* XXX: should this be ENXIO? */ + } cs = device_lookup_private(&cgd_cd, unit); if (cs == NULL || !DK_ATTACHED(dksc)) { @@ -836,6 +875,7 @@ cgd_ioctl_get(dev_t dev, void *data, str cgu->cgu_mode = cs->sc_cdata.cf_mode; cgu->cgu_keylen = cs->sc_cdata.cf_keylen; } + cgd_release(dev); return 0; } @@ -1030,7 +1070,7 @@ hexprint(const char *start, void *buf, i MODULE(MODULE_CLASS_DRIVER, cgd, "dk_subr"); #ifdef _MODULE -CFDRIVER_DECL(cgd, DV_DISK, NULL); +#include "ioconf.c" #endif static int @@ -1051,8 +1091,8 @@ cgd_modcmd(modcmd_t cmd, void *arg) error = config_init_component(cfdriver_ioconf_cgd, cfattach_ioconf_cgd, cfdata_ioconf_cgd); if (error) { - aprint_error("%s: unable to init component", - cgd_cd.cd_name); + aprint_error("%s: unable to init component" + ", error %d", cgd_cd.cd_name, error); break; } @@ -1068,8 +1108,8 @@ cgd_modcmd(modcmd_t cmd, void *arg) if (error) { config_fini_component(cfdriver_ioconf_cgd, cfattach_ioconf_cgd, cfdata_ioconf_cgd); - aprint_error("%s: unable to attach devsw", - cgd_cd.cd_name); + aprint_error("%s: unable to attach devsw" + ", error %d", cgd_cd.cd_name, error); } #endif break; @@ -1090,9 +1130,12 @@ cgd_modcmd(modcmd_t cmd, void *arg) /* * If removal fails, re-attach our {b,c}devsw's */ - if (error) + if (error) { + aprint_error("%s: failed to remove from autoconf" + ", error %d", cgd_cd.cd_name, error); devsw_attach("cgd", &cgd_bdevsw, &bmajor, &cgd_cdevsw, &cmajor); + } #endif break;