From 1af2d09b4943a41ad364d8ea63dba461f02cc21d Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Mon, 29 Oct 2012 17:52:43 +0000 Subject: Fix locking problem in disk_resize(); previously it would run without topology lock, resulting in assertion when running with DIAGNOSTIC. Reviewed by: mav (earlier version) --- sys/cam/scsi/scsi_da.c | 8 ++++---- sys/geom/geom_disk.c | 36 +++++++++++++++--------------------- sys/geom/geom_disk.h | 2 +- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 315df583eccd..adda9c9b7efa 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -2673,6 +2673,7 @@ dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector, struct da_softc *softc; struct disk_params *dp; u_int lbppbe, lalba; + int error; softc = (struct da_softc *)periph->softc; @@ -2779,10 +2780,9 @@ dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector, else softc->disk->d_flags &= ~DISKFLAG_CANDELETE; -/* Currently as of 6/13/2012, panics if DIAGNOSTIC is set */ -#ifndef DIAGNOSTIC - disk_resize(softc->disk); -#endif + error = disk_resize(softc->disk, M_NOWAIT); + if (error != 0) + xpt_print(periph->path, "disk_resize(9) failed, error = %d\n", error); } static void diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 12ad61209e1d..72e9162578a4 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -66,7 +65,6 @@ struct g_disk_softc { struct sysctl_oid *sysctl_tree; char led[64]; uint32_t state; - struct task resize_task; }; static struct mtx g_disk_done_mtx; @@ -443,17 +441,22 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g } static void -g_disk_resize_task(void *context, int pending) +g_disk_resize(void *ptr, int flag) { + struct disk *dp; struct g_geom *gp; struct g_provider *pp; - struct disk *dp; - struct g_disk_softc *sc; - sc = (struct g_disk_softc *)context; - dp = sc->dp; + if (flag == EV_CANCEL) + return; + g_topology_assert(); + + dp = ptr; gp = dp->d_geom; + if (dp->d_destroyed || gp == NULL) + return; + LIST_FOREACH(pp, &gp->provider, provider) { if (pp->sectorsize != 0 && pp->sectorsize != dp->d_sectorsize) @@ -501,7 +504,6 @@ g_disk_create(void *arg, int flag) CTLFLAG_RW | CTLFLAG_TUN, sc->led, sizeof(sc->led), "LED name"); } - TASK_INIT(&sc->resize_task, 0, g_disk_resize_task, sc); pp->private = sc; dp->d_geom = gp; g_error_provider(pp, 0); @@ -684,22 +686,14 @@ disk_media_gone(struct disk *dp, int flag) } } -void -disk_resize(struct disk *dp) +int +disk_resize(struct disk *dp, int flag) { - struct g_geom *gp; - struct g_disk_softc *sc; - int error; - gp = dp->d_geom; - - if (gp == NULL) - return; - - sc = gp->softc; + if (dp->d_destroyed || dp->d_geom == NULL) + return (0); - error = taskqueue_enqueue(taskqueue_thread, &sc->resize_task); - KASSERT(error == 0, ("taskqueue_enqueue(9) failed.")); + return (g_post_event(g_disk_resize, dp, flag, NULL)); } static void diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h index cf538395fa35..33d8eb206ab9 100644 --- a/sys/geom/geom_disk.h +++ b/sys/geom/geom_disk.h @@ -111,7 +111,7 @@ void disk_gone(struct disk *disk); void disk_attr_changed(struct disk *dp, const char *attr, int flag); void disk_media_changed(struct disk *dp, int flag); void disk_media_gone(struct disk *dp, int flag); -void disk_resize(struct disk *dp); +int disk_resize(struct disk *dp, int flag); #define DISK_VERSION_00 0x58561059 #define DISK_VERSION_01 0x5856105a -- cgit v1.2.3