diff options
author | trasz <trasz@FreeBSD.org> | 2012-10-29 17:52:43 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2012-10-29 17:52:43 +0000 |
commit | 76f8fadfa80a4732a2670b0032c3ac3fc89da8c7 (patch) | |
tree | 2d9f20d733600dd0e847700629b04cc73da7ca64 | |
parent | 7fb492fc1b3aa6bb7675572bf9680bb612682996 (diff) | |
download | FreeBSD-src-76f8fadfa80a4732a2670b0032c3ac3fc89da8c7.zip FreeBSD-src-76f8fadfa80a4732a2670b0032c3ac3fc89da8c7.tar.gz |
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)
-rw-r--r-- | sys/cam/scsi/scsi_da.c | 8 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 36 | ||||
-rw-r--r-- | 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 315df58..adda9c9 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 12ad612..72e9162 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/sbuf.h> #include <sys/sysctl.h> -#include <sys/taskqueue.h> #include <sys/devicestat.h> #include <machine/md_var.h> @@ -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 cf53839..33d8eb2 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 |