Works on my crypto volume. People with other volume types would be nice
to hear from.
.... Ken
Index: softraid.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid.c,v
retrieving revision 1.222
diff -u -p -r1.222 softraid.c
--- softraid.c 15 Mar 2011 13:29:41 -0000 1.222
+++ softraid.c 3 Apr 2011 21:07:48 -0000
@@ -1805,7 +1805,7 @@ sr_wu_alloc(struct sr_discipline *sd)
for (i = 0; i < no_wu; i++) {
wu = &sd->sd_wu[i];
wu->swu_dis = sd;
- sr_wu_put(wu);
+ sr_wu_put(sd, wu);
}
return (0);
@@ -1833,17 +1833,15 @@ sr_wu_free(struct sr_discipline *sd)
}
void
-sr_wu_put(struct sr_workunit *wu)
+sr_wu_put(void *xsd, void *xwu)
{
- struct sr_discipline *sd = wu->swu_dis;
+ struct sr_discipline *sd = (struct sr_discipline *)xsd;
+ struct sr_workunit *wu = (struct sr_workunit *)xwu;
struct sr_ccb *ccb;
-
int s;
DNPRINTF(SR_D_WU, "%s: sr_wu_put: %p\n", DEVNAME(sd->sd_sc), wu);
- s = splbio();
-
wu->swu_xs = NULL;
wu->swu_state = SR_WU_FREE;
wu->swu_ios_complete = 0;
@@ -1864,9 +1862,12 @@ sr_wu_put(struct sr_workunit *wu)
}
TAILQ_INIT(&wu->swu_ccb);
+ mtx_enter(&sd->sd_wu_mtx);
TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link);
sd->sd_wu_pending--;
+ mtx_leave(&sd->sd_wu_mtx);
+ s = splbio();
/* wake up sleepers */
#ifdef DIAGNOSTIC
if (sd->sd_wu_sleep < 0)
@@ -1874,34 +1875,23 @@ sr_wu_put(struct sr_workunit *wu)
#endif /* DIAGNOSTIC */
if (sd->sd_wu_sleep)
wakeup(&sd->sd_wu_sleep);
-
splx(s);
}
-struct sr_workunit *
-sr_wu_get(struct sr_discipline *sd, int canwait)
+void *
+sr_wu_get(void *xsd)
{
+ struct sr_discipline *sd = (struct sr_discipline *)xsd;
struct sr_workunit *wu;
- int s;
-
- s = splbio();
- 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;
+ mtx_enter(&sd->sd_wu_mtx);
+ 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++;
}
-
- splx(s);
+ mtx_leave(&sd->sd_wu_mtx);
DNPRINTF(SR_D_WU, "%s: sr_wu_get: %p\n", DEVNAME(sd->sd_sc), wu);
@@ -1949,19 +1939,9 @@ sr_scsi_cmd(struct scsi_xfer *xs)
goto stuffup;
}
- /*
- * 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));
- xs->error = XS_NO_CCB;
- sr_scsi_done(sd, xs);
- return;
- }
-
- xs->error = XS_NOERROR;
+ wu = xs->io;
wu->swu_xs = xs;
+ xs->error = XS_NOERROR;
/* the midlayer will query LUNs so report sense to stop scanning */
if (link->target != 0 || link->lun != 0) {
@@ -2049,10 +2029,9 @@ stuffup:
xs->error = XS_DRIVER_STUFFUP;
}
complete:
- if (wu)
- sr_wu_put(wu);
sr_scsi_done(sd, xs);
}
+
int
sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
{
@@ -3042,6 +3021,8 @@ sr_ioctl_createraid(struct sr_softc *sc,
}
/* setup scsi midlayer */
+ mtx_init(&sd->sd_wu_mtx, IPL_BIO);
+ scsi_iopool_init(&sd->sd_iopool, sd, sr_wu_get, sr_wu_put);
if (sd->sd_openings)
sd->sd_link.openings = sd->sd_openings(sd);
else
@@ -3051,6 +3032,7 @@ sr_ioctl_createraid(struct sr_softc *sc,
sd->sd_link.adapter = &sr_switch;
sd->sd_link.adapter_target = SR_MAX_LD;
sd->sd_link.adapter_buswidth = 1;
+ sd->sd_link.pool = &sd->sd_iopool;
bzero(&saa, sizeof(saa));
saa.saa_sc_link = &sd->sd_link;
@@ -3953,11 +3935,17 @@ sr_rebuild_thread(void *arg)
mysize += sz;
lba = blk * sz;
- /* 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));
+ /* Waiting for the required work units is allowed. */
+ while ((wu_r = sr_wu_get(sd)) == NULL) {
+ sd->sd_wu_sleep++;
+ tsleep(&sd->sd_wu_sleep, PRIBIO, "sr_wu_get", 0);
+ sd->sd_wu_sleep--;
+ }
+ while ((wu_w = sr_wu_get(sd)) == NULL) {
+ sd->sd_wu_sleep++;
+ tsleep(&sd->sd_wu_sleep, PRIBIO, "sr_wu_get", 0);
+ sd->sd_wu_sleep--;
+ }
/* setup read io */
bzero(&xs_r, sizeof xs_r);
@@ -4009,11 +3997,8 @@ sr_rebuild_thread(void *arg)
TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu_w, swu_link);
/* schedule io */
- if (sr_check_io_collision(wu_r))
- goto queued;
-
- sr_raid_startwu(wu_r);
-queued:
+ if (sr_check_io_collision(wu_r) == 0)
+ sr_raid_startwu(wu_r);
splx(s);
/* wait for read completion */
@@ -4026,8 +4011,8 @@ queued:
if (slept == 0)
tsleep(sc, PWAIT, "sr_yield", 1);
- sr_wu_put(wu_r);
- sr_wu_put(wu_w);
+ sr_wu_put(sd, wu_r);
+ sr_wu_put(sd, wu_w);
sd->sd_meta->ssd_rebuild = lba;
Index: softraid_aoe.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_aoe.c,v
retrieving revision 1.17
diff -u -p -r1.17 softraid_aoe.c
--- softraid_aoe.c 2 Jul 2010 15:49:25 -0000 1.17
+++ softraid_aoe.c 3 Apr 2011 22:14:12 -0000
@@ -511,7 +511,7 @@ sr_aoe_input(struct aoe_handler *ah, str
struct aoe_packet *ap;
struct sr_workunit *wu, *wup;
daddr64_t blk, offset;
- int len, s;
+ int len, s, done = 0;
int tag;
ap = mtod(m, struct aoe_packet *);
@@ -576,10 +576,9 @@ sr_aoe_input(struct aoe_handler *ah, str
break;
}
}
-
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
+ splx(s);
sr_scsi_done(sd, xs);
+ s = splbio();
}
out:
Index: softraid_crypto.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_crypto.c,v
retrieving revision 1.63
diff -u -p -r1.63 softraid_crypto.c
--- softraid_crypto.c 6 Mar 2011 21:41:57 -0000 1.63
+++ softraid_crypto.c 3 Apr 2011 22:16:36 -0000
@@ -1134,7 +1134,6 @@ sr_crypto_rw(struct sr_workunit *wu)
int
sr_crypto_write(struct cryptop *crp)
{
- int s;
struct sr_workunit *wu = crp->crp_opaque;
DNPRINTF(SR_D_INTR, "%s: sr_crypto_write: wu %x xs: %x\n",
@@ -1144,9 +1143,7 @@ sr_crypto_write(struct cryptop *crp)
/* fail io */
((struct sr_workunit *)(crp->crp_opaque))->swu_xs->error =
XS_DRIVER_STUFFUP;
- s = splbio();
sr_crypto_finish_io(crp->crp_opaque);
- splx(s);
}
return (sr_crypto_rw2(wu, crp));
@@ -1216,13 +1213,8 @@ sr_crypto_rw2(struct sr_workunit *wu, st
ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
s = splbio();
-
- if (sr_check_io_collision(wu))
- goto queued;
-
- sr_raid_startwu(wu);
-
-queued:
+ if (sr_check_io_collision(wu) == 0)
+ sr_raid_startwu(wu);
splx(s);
return (0);
bad:
@@ -1313,7 +1305,9 @@ sr_crypto_intr(struct buf *bp)
goto done;
}
+ splx(s);
sr_crypto_finish_io(wu);
+ s = splbio();
}
done:
@@ -1329,12 +1323,13 @@ sr_crypto_finish_io(struct sr_workunit *
#ifdef SR_DEBUG
struct sr_softc *sc = sd->sd_sc;
#endif /* SR_DEBUG */
+ int s;
- splassert(IPL_BIO);
DNPRINTF(SR_D_INTR, "%s: sr_crypto_finish_io: wu %x xs: %x\n",
DEVNAME(sc), wu, xs);
+ s = splbio();
xs->resid = 0;
if (wu->swu_cb_active == 1)
@@ -1345,18 +1340,16 @@ sr_crypto_finish_io(struct sr_workunit *
sr_crypto_putcryptop(ccb->ccb_opaque);
}
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- sr_scsi_done(sd, xs);
-
if (sd->sd_sync && sd->sd_wu_pending == 0)
wakeup(sd);
+
+ splx(s);
+ sr_scsi_done(sd, xs);
}
int
sr_crypto_read(struct cryptop *crp)
{
- int s;
struct sr_workunit *wu = crp->crp_opaque;
DNPRINTF(SR_D_INTR, "%s: sr_crypto_read: wu %x xs: %x\n",
@@ -1365,9 +1358,7 @@ sr_crypto_read(struct cryptop *crp)
if (crp->crp_etype)
wu->swu_xs->error = XS_DRIVER_STUFFUP;
- s = splbio();
sr_crypto_finish_io(wu);
- splx(s);
return (0);
}
Index: softraid_raid0.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raid0.c,v
retrieving revision 1.22
diff -u -p -r1.22 softraid_raid0.c
--- softraid_raid0.c 2 Jul 2010 09:20:26 -0000 1.22
+++ softraid_raid0.c 3 Apr 2011 22:18:12 -0000
@@ -370,12 +370,8 @@ sr_raid0_rw(struct sr_workunit *wu)
}
s = splbio();
-
- if (sr_check_io_collision(wu))
- goto queued;
-
- sr_raid_startwu(wu);
-queued:
+ if (sr_check_io_collision(wu) == 0)
+ sr_raid_startwu(wu);
splx(s);
return (0);
bad:
@@ -456,9 +452,9 @@ sr_raid0_intr(struct buf *bp)
printf("%s: wu: %p not on pending queue\n",
DEVNAME(sc), wu);
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
+ splx(s);
sr_scsi_done(sd, xs);
+ s = splbio();
if (sd->sd_sync && sd->sd_wu_pending == 0)
wakeup(sd);
@@ -468,7 +464,6 @@ sr_raid0_intr(struct buf *bp)
return;
bad:
xs->error = XS_DRIVER_STUFFUP;
- sr_wu_put(wu);
- sr_scsi_done(sd, xs);
splx(s);
+ sr_scsi_done(sd, xs);
}
Index: softraid_raid1.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raid1.c,v
retrieving revision 1.26
diff -u -p -r1.26 softraid_raid1.c
--- softraid_raid1.c 6 Nov 2010 23:01:56 -0000 1.26
+++ softraid_raid1.c 3 Apr 2011 22:04:56 -0000
@@ -615,9 +615,9 @@ sr_raid1_intr(struct buf *bp)
wakeup(wu);
}
} else {
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- scsi_done(xs);
+ splx(s);
+ sr_scsi_done(sd, xs);
+ s = splbio();
}
if (sd->sd_sync && sd->sd_wu_pending == 0)
@@ -632,13 +632,11 @@ bad:
if (wu->swu_flags & SR_WUF_REBUILD) {
wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
wakeup(wu);
+ splx(s);
} else {
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- scsi_done(xs);
+ splx(s);
+ sr_scsi_done(sd, xs);
}
-
- splx(s);
}
void
Index: softraid_raid6.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raid6.c,v
retrieving revision 1.19
diff -u -p -r1.19 softraid_raid6.c
--- softraid_raid6.c 7 Aug 2010 03:50:01 -0000 1.19
+++ softraid_raid6.c 3 Apr 2011 21:19:24 -0000
@@ -480,7 +480,7 @@ sr_raid6_rw(struct sr_workunit *wu)
rwmode = (xs->flags & SCSI_DATA_IN) ? M_RFLG : M_WFLG;
if (xs->flags & SCSI_DATA_OUT)
/* create write workunit */
- if ((wu_w = sr_wu_get(sd, 0)) == NULL) {
+ if ((wu_w = sr_wu_get(sd)) == NULL) {
printf("%s: can't get wu_w", DEVNAME(sd->sd_sc));
goto bad;
}
@@ -744,7 +744,7 @@ queued:
bad:
/* wu is unwound by sr_wu_put */
if (wu_w)
- sr_wu_put(wu_w);
+ sr_wu_put(sd, wu_w);
return (1);
}
@@ -888,11 +888,12 @@ sr_raid6_intr(struct buf *bp)
wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
wakeup(wu);
}
+ } else if (xs == NULL) {
+ sr_wu_put(sd, wu);
} else {
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- if (xs != NULL)
- scsi_done(xs);
+ splx(s);
+ sr_scsi_done(sd, xs);
+ s = splbio();
}
if (sd->sd_sync && sd->sd_wu_pending == 0)
@@ -907,13 +908,11 @@ bad:
if (wu->swu_flags & SR_WUF_REBUILD) {
wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
wakeup(wu);
+ splx(s);
} else {
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- scsi_done(xs);
+ splx(s);
+ sr_scsi_done(sd, xs);
}
-
- splx(s);
}
void
Index: softraid_raidp.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raidp.c,v
retrieving revision 1.19
diff -u -p -r1.19 softraid_raidp.c
--- softraid_raidp.c 7 Aug 2010 03:50:01 -0000 1.19
+++ softraid_raidp.c 3 Apr 2011 21:19:58 -0000
@@ -396,7 +396,7 @@ sr_raidp_rw(struct sr_workunit *wu)
if (xs->flags & SCSI_DATA_OUT)
/* create write workunit */
- if ((wu_w = sr_wu_get(sd, 0)) == NULL) {
+ if ((wu_w = sr_wu_get(sd)) == NULL) {
printf("%s: can't get wu_w", DEVNAME(sd->sd_sc));
goto bad;
}
@@ -553,7 +553,7 @@ queued:
bad:
/* wu is unwound by sr_wu_put */
if (wu_w)
- sr_wu_put(wu_w);
+ sr_wu_put(sd, wu_w);
return (1);
}
@@ -670,9 +670,13 @@ sr_raidp_intr(struct buf *bp)
}
} else {
/* do not change the order of these 2 functions */
- sr_wu_put(wu);
- if (xs != NULL)
- scsi_done(xs);
+ if (xs == NULL)
+ sr_wu_put(sd, wu);
+ else {
+ splx(s);
+ sr_scsi_done(sd, xs);
+ s = splbio();
+ }
}
if (sd->sd_sync && sd->sd_wu_pending == 0)
@@ -687,13 +691,11 @@ bad:
if (wu->swu_flags & SR_WUF_REBUILD) {
wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
wakeup(wu);
+ splx(s);
} else {
- /* do not change the order of these 2 functions */
- sr_wu_put(wu);
- scsi_done(xs);
+ splx(s);
+ sr_scsi_done(sd, xs);
}
-
- splx(s);
}
void
@@ -831,10 +833,17 @@ sr_raidp_scrub(struct sr_discipline *sd)
int s, slept;
void *xorbuf;
- if ((wu_r = sr_wu_get(sd, 1)) == NULL)
- goto done;
- if ((wu_w = sr_wu_get(sd, 1)) == NULL)
- goto done;
+ /* Waiting for the required work units is allowed. */
+ while ((wu_r = sr_wu_get(sd)) == NULL) {
+ sd->sd_wu_sleep++;
+ tsleep(&sd->sd_wu_sleep, PRIBIO, "sr_wu_get", 0);
+ sd->sd_wu_sleep--;
+ }
+ while ((wu_w = sr_wu_get(sd)) == NULL) {
+ sd->sd_wu_sleep++;
+ tsleep(&sd->sd_wu_sleep, PRIBIO, "sr_wu_get", 0);
+ sd->sd_wu_sleep--;
+ }
no_chunk = sd->sd_meta->ssdi.ssd_chunk_no - 1;
strip_size = sd->sd_meta->ssdi.ssd_strip_size;
Index: softraidvar.h
===================================================================
RCS file: /cvs/src/sys/dev/softraidvar.h,v
retrieving revision 1.98
diff -u -p -r1.98 softraidvar.h
--- softraidvar.h 15 Mar 2011 13:29:41 -0000 1.98
+++ softraidvar.h 3 Apr 2011 20:46:10 -0000
@@ -526,6 +526,9 @@ struct sr_discipline {
struct sr_wu_list sd_wu_defq; /* deferred wu queue */
int sd_wu_sleep; /* wu sleepers counter */
+ struct mutex sd_wu_mtx;
+ struct scsi_iopool sd_iopool;
+
/* discipline stats */
int sd_wu_pending;
u_int64_t sd_wu_collisions;
@@ -604,8 +607,8 @@ struct sr_ccb *sr_ccb_get(struct sr_dis
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 *, int);
-void sr_wu_put(struct sr_workunit *);
+void *sr_wu_get(void *);
+void sr_wu_put(void *, void *);
/* misc functions */
int32_t sr_validate_stripsize(u_int32_t);