diff options
author | phk <phk@FreeBSD.org> | 2002-10-11 20:52:44 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-10-11 20:52:44 +0000 |
commit | 1a10e2f35a4be7790f519238f8b6491bea83d6f2 (patch) | |
tree | 5da35adbd137bda54d9e4de2dde95118045aec76 /sys/geom | |
parent | 109f9bf9eb5b194938817ea5d4e9aca09eea9e51 (diff) | |
download | FreeBSD-src-1a10e2f35a4be7790f519238f8b6491bea83d6f2.zip FreeBSD-src-1a10e2f35a4be7790f519238f8b6491bea83d6f2.tar.gz |
The CAM system has it's own ideas of what locks are to be held by whom.
So do GEOM. Not a pretty sight.
Take all the interesting stuff out of GEOM::disk_create(), and leave just
the creation of the fake dev_t. Schedule the topology munging to happen
in the g_event thread with g_call_me().
This makes disk_create() pretty lock-agnostic, almost lock-atheist.
Tripped over by: peter
Sponsored by: DARPA & NAI Labs
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/geom_disk.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 006ff32..0e9a150 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -66,6 +66,8 @@ struct g_class g_disk_class = { G_CLASS_INITIALIZER }; +DECLARE_GEOM_CLASS(g_disk_class, g_disk); + static int g_disk_access(struct g_provider *pp, int r, int w, int e) { @@ -203,36 +205,39 @@ g_disk_start(struct bio *bp) return; } -dev_t -disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) +static void +g_disk_create(void *arg) { - static int once; struct g_geom *gp; struct g_provider *pp; dev_t dev; - mtx_unlock(&Giant); - if (!once) { - g_add_class(&g_disk_class); - once++; - } + g_topology_assert(); + dev = arg; + gp = g_new_geomf(&g_disk_class, dev->si_name); + gp->start = g_disk_start; + gp->access = g_disk_access; + gp->softc = dev->si_disk; + dev->si_disk->d_softc = gp; + pp = g_new_providerf(gp, "%s", gp->name); + g_error_provider(pp, 0); +} + + + +dev_t +disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) +{ + dev_t dev; + dev = g_malloc(sizeof *dev, M_WAITOK | M_ZERO); dp->d_dev = dev; dp->d_devsw = cdevsw; dev->si_devsw = cdevsw; dev->si_disk = dp; dev->si_udev = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART); - g_topology_lock(); - gp = g_new_geomf(&g_disk_class, "%s%d", cdevsw->d_name, unit); - strcpy(dev->si_name, gp->name); - gp->start = g_disk_start; - gp->access = g_disk_access; - gp->softc = dp; - dp->d_softc = gp; - pp = g_new_providerf(gp, "%s", gp->name); - g_error_provider(pp, 0); - g_topology_unlock(); - mtx_lock(&Giant); + sprintf(dev->si_name, "%s%d", cdevsw->d_name, unit); + g_call_me(g_disk_create, dev); return (dev); } |