summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/softraid.c78
-rw-r--r--sys/dev/softraidvar.h9
2 files changed, 60 insertions, 27 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index ec377b44388..18dc1eb46dc 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.144 2009/06/03 17:39:26 ckuethe Exp $ */
+/* $OpenBSD: softraid.c,v 1.145 2009/06/03 21:04:36 marco Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -1470,23 +1470,39 @@ sr_wu_put(struct sr_workunit *wu)
TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link);
sd->sd_wu_pending--;
+ /* wake up sleepers */
+#ifdef DIAGNOSTIC
+ if (sd->sd_wu_sleep < 0)
+ panic("negative wu sleepers");
+#endif /* DIAGNOSTIC */
+ if (sd->sd_wu_sleep)
+ wakeup(&sd->sd_wu_sleep);
+
splx(s);
}
struct sr_workunit *
-sr_wu_get(struct sr_discipline *sd)
+sr_wu_get(struct sr_discipline *sd, int canwait)
{
struct sr_workunit *wu;
int s;
s = splbio();
- wu = TAILQ_FIRST(&sd->sd_wu_freeq);
- if (wu) {
- TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
- wu->swu_state = SR_WU_INPROGRESS;
+ for (;;) {
+ wu = TAILQ_FIRST(&sd->sd_wu_freeq);
+ if (wu) {
+ TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
+ wu->swu_state = SR_WU_INPROGRESS;
+ sd->sd_wu_pending++;
+ break;
+ } else if (wu == NULL && canwait) {
+ sd->sd_wu_sleep++;
+ tsleep(&sd->sd_wu_sleep, PRIBIO, "sr_wu_get", 0);
+ sd->sd_wu_sleep--;
+ } else
+ break;
}
- sd->sd_wu_pending++;
splx(s);
@@ -1541,7 +1557,11 @@ sr_scsi_cmd(struct scsi_xfer *xs)
goto stuffup;
}
- if ((wu = sr_wu_get(sd)) == NULL) {
+ /*
+ * we'll let the midlayer deal with stalls instead of being clever
+ * and sending sr_wu_get !(xs->flags & SCSI_NOSLEEP) in cansleep
+ */
+ if ((wu = sr_wu_get(sd, 0)) == NULL) {
DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd no wu\n", DEVNAME(sc));
return (NO_CCB);
}
@@ -1931,7 +1951,7 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
goto done;
}
- printf("%s: trying rebuild %s from %s\n", DEVNAME(sc),
+ printf("%s: trying to rebuild %s to %s\n", DEVNAME(sc),
sd->sd_meta->ssd_devname, devname);
kthread_create_deferred(sr_rebuild, sd);
@@ -2866,6 +2886,15 @@ sr_rebuild_thread(void *arg)
restart = 0;
}
if (restart) {
+ /*
+ * XXX there is a hole here; there is a posibility that we
+ * had a restart however the chunk that was supposed to
+ * be rebuilt is no longer valid; we can reach this situation
+ * when a rebuild is in progress and the box crashes and
+ * on reboot the rebuild chunk is different (like zero'd or
+ * replaced). We need to check the uuid of the chunk that is
+ * being rebuilt to assert this.
+ */
psz = sd->sd_meta->ssdi.ssd_size;
rb = sd->sd_meta->ssd_rebuild;
percent = 100 - ((psz * 100 - rb * 100) / psz);
@@ -2884,9 +2913,11 @@ sr_rebuild_thread(void *arg)
mysize += sz;
lba = blk * sz;
- /* XXX be nicer than panic */
- if ((wu_r = sr_wu_get(sd)) == NULL)
+ /* get some wu */
+ if ((wu_r = sr_wu_get(sd, 1)) == NULL)
panic("%s: rebuild exhausted wu_r", DEVNAME(sc));
+ if ((wu_w = sr_wu_get(sd, 1)) == NULL)
+ panic("%s: rebuild exhausted wu_w", DEVNAME(sc));
/* setup read io */
bzero(&xs_r, sizeof xs_r);
@@ -2900,15 +2931,13 @@ sr_rebuild_thread(void *arg)
_lto4b(sz, cr.length);
_lto8b(lba, cr.addr);
xs_r.cmd = (struct scsi_generic *)&cr;
- wu_r->swu_flags = SR_WUF_REBUILD;
+ wu_r->swu_flags |= SR_WUF_REBUILD;
wu_r->swu_xs = &xs_r;
- /* XXX be nicer than panic */
- if (sd->sd_scsi_rw(wu_r))
- panic("read failed");
-
- /* XXX be nicer than panic */
- if ((wu_w = sr_wu_get(sd)) == NULL)
- panic("%s: rebuild exhausted wu_w", DEVNAME(sc));
+ if (sd->sd_scsi_rw(wu_r)) {
+ printf("%s: could not create read io\n",
+ DEVNAME(sc));
+ goto fail;
+ }
/* setup write io */
bzero(&xs_w, sizeof xs_w);
@@ -2922,10 +2951,13 @@ sr_rebuild_thread(void *arg)
_lto4b(sz, cw.length);
_lto8b(lba, cw.addr);
xs_w.cmd = (struct scsi_generic *)&cw;
- wu_w->swu_flags = SR_WUF_REBUILD;
+ wu_w->swu_flags |= SR_WUF_REBUILD;
wu_w->swu_xs = &xs_w;
- if (sd->sd_scsi_rw(wu_w))
- panic("write failed");
+ if (sd->sd_scsi_rw(wu_w)) {
+ printf("%s: could not create write io\n",
+ DEVNAME(sc));
+ goto fail;
+ }
/*
* collide with the read io so that we get automatically
@@ -2987,7 +3019,7 @@ abort:
if (sr_meta_save(sd, SR_META_DIRTY))
printf("%s: could not save metadata to %s\n",
DEVNAME(sc), sd->sd_meta->ssd_devname);
-
+fail:
free(buf, M_DEVBUF);
sd->sd_reb_active = 0;
kthread_exit(0);
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index f25e95a3d74..7b9156b0d36 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.70 2009/06/02 19:15:58 marco Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.71 2009/06/03 21:04:36 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -256,8 +256,8 @@ struct sr_workunit {
#define SR_WU_REQUEUE 8
int swu_flags; /* additional hints */
-#define SR_WUF_REBUILD (1<<0)
-#define SR_WUF_REBUILDIOCOMP (1<<1)
+#define SR_WUF_REBUILD (1<<0) /* rebuild io */
+#define SR_WUF_REBUILDIOCOMP (1<<1) /* rbuild io complete */
int swu_fake; /* faked wu */
/* workunit io range */
@@ -411,6 +411,7 @@ struct sr_discipline {
struct sr_wu_list sd_wu_freeq; /* free wu queue */
struct sr_wu_list sd_wu_pendq; /* pending wu queue */
struct sr_wu_list sd_wu_defq; /* deferred wu queue */
+ int sd_wu_sleep; /* wu sleepers counter */
/* discipline stats */
int sd_wu_pending;
@@ -467,7 +468,7 @@ struct sr_ccb *sr_ccb_get(struct sr_discipline *);
void sr_ccb_put(struct sr_ccb *);
int sr_wu_alloc(struct sr_discipline *);
void sr_wu_free(struct sr_discipline *);
-struct sr_workunit *sr_wu_get(struct sr_discipline *);
+struct sr_workunit *sr_wu_get(struct sr_discipline *, int);
void sr_wu_put(struct sr_workunit *);
/* misc functions */