aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2012-10-29 17:52:43 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2012-10-29 17:52:43 +0000
commit1af2d09b4943a41ad364d8ea63dba461f02cc21d (patch)
tree2d9f20d733600dd0e847700629b04cc73da7ca64
parenta9387eb1df40b3c027e3791339c10f4b19587c26 (diff)
downloadsrc-1af2d09b4943a41ad364d8ea63dba461f02cc21d.tar.gz
src-1af2d09b4943a41ad364d8ea63dba461f02cc21d.zip
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)
Notes
Notes: svn path=/head/; revision=242322
-rw-r--r--sys/cam/scsi/scsi_da.c8
-rw-r--r--sys/geom/geom_disk.c36
-rw-r--r--sys/geom/geom_disk.h2
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 <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 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