summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2009-06-17 22:45:42 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2009-06-17 22:45:42 +0000
commit89ae8a19aa82210ba492f252aca8b5db868ce984 (patch)
tree4ed8d6fd89a8d5c5d9df432d52ad090555db5435
parent851100dc32d2b98d73cd416c018ed5ef8f653c57 (diff)
Added openings callback; cleanup & KNF
I/O now works reliably ok marco@
-rw-r--r--sys/dev/softraid_raidp.c169
1 files changed, 101 insertions, 68 deletions
diff --git a/sys/dev/softraid_raidp.c b/sys/dev/softraid_raidp.c
index 1dd77e1bfcd..475d3160c60 100644
--- a/sys/dev/softraid_raidp.c
+++ b/sys/dev/softraid_raidp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_raidp.c,v 1.4 2009/06/13 00:14:56 jordan Exp $ */
+/* $OpenBSD: softraid_raidp.c,v 1.5 2009/06/17 22:45:41 jordan Exp $ */
/*
* Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2009 Jordan Hargrave <jordan@openbsd.org>
@@ -48,6 +48,7 @@
int sr_raidp_alloc_resources(struct sr_discipline *);
int sr_raidp_free_resources(struct sr_discipline *);
int sr_raidp_rw(struct sr_workunit *);
+int sr_raidp_openings(struct sr_discipline *);
void sr_raidp_intr(struct buf *);
void sr_raidp_recreate_wu(struct sr_workunit *);
void sr_raidp_set_chunk_state(struct sr_discipline *, int, int);
@@ -59,17 +60,20 @@ int sr_raidp_addio(struct sr_workunit *wu, int, daddr64_t, daddr64_t,
void sr_dump(void *, int);
void sr_raidp_scrub(struct sr_discipline *);
-/* Discipline initialisation. */
+void *sr_get_block(struct sr_discipline *, int);
+void sr_put_block(struct sr_discipline *, void *);
+
+/* discipline initialisation. */
void
sr_raidp_discipline_init(struct sr_discipline *sd)
{
- /* Fill out discipline members. */
- sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
+ /* fill out discipline members. */
+ sd->sd_max_ccb_per_wu = 4; /* only if stripsize <= MAXPHYS */
sd->sd_max_wu = SR_RAIDP_NOWU;
- sd->sd_rebuild = 1;
+ sd->sd_rebuild = 0;
- /* Setup discipline pointers. */
+ /* setup discipline pointers. */
sd->sd_alloc_resources = sr_raidp_alloc_resources;
sd->sd_free_resources = sr_raidp_free_resources;
sd->sd_start_discipline = NULL;
@@ -82,6 +86,13 @@ sr_raidp_discipline_init(struct sr_discipline *sd)
sd->sd_scsi_rw = sr_raidp_rw;
sd->sd_set_chunk_state = sr_raidp_set_chunk_state;
sd->sd_set_vol_state = sr_raidp_set_vol_state;
+ sd->sd_openings = sr_raidp_openings;
+}
+
+int
+sr_raidp_openings(struct sr_discipline *sd)
+{
+ return (sd->sd_max_wu >> 1); /* 2 wu's per IO */
}
int
@@ -134,6 +145,7 @@ sr_raidp_set_chunk_state(struct sr_discipline *sd, int c, int new_state)
{
int old_state, s;
+ /* XXX this is for RAID 0 */
DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state);
@@ -213,6 +225,8 @@ sr_raidp_set_vol_state(struct sr_discipline *sd)
int new_state, i, s, nd;
int old_state = sd->sd_vol_status;
+ /* XXX this is for RAID 0 */
+
DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);
@@ -352,13 +366,9 @@ sr_raidp_rw(struct sr_workunit *wu)
datalen = xs->datalen;
lbaoffs = blk << DEV_BSHIFT;
-#if 0
- printf("0000: sr_raidp_%s: blk=%llx len=%llx\n",
- xs->flags & SCSI_DATA_IN ? "rd" : "wr", blk, datalen);
-#endif
if (xs->flags & SCSI_DATA_OUT)
- /* Create Write workunit */
- if ((wu_w = sr_wu_get(sd, 1)) == NULL) {
+ /* create write workunit */
+ if ((wu_w = sr_wu_get(sd, 0)) == NULL) {
printf("%s: can't get wu_w", DEVNAME(sd->sd_sc));
goto bad;
}
@@ -371,16 +381,15 @@ sr_raidp_rw(struct sr_workunit *wu)
phys_offs = chunk_offs + strip_offs +
((SR_META_OFFSET + SR_META_SIZE) << DEV_BSHIFT);
- /* Get size remaining in this stripe */
+ /* get size remaining in this stripe */
length = MIN(strip_size - strip_offs, datalen);
- /* Map disk offset to parity/data drive */
+ /* map disk offset to parity/data drive */
chunk = strip_no % no_chunk;
if (sd->sd_type == SR_MD_RAID4)
- /* RAID4: Parity is always drive N */
- parity = no_chunk;
+ parity = no_chunk; /* RAID4: Parity is always drive N */
else {
- /* RAID5: Left Asymmetric algorithm */
+ /* RAID5: left asymmetric algorithm */
parity = no_chunk - ((strip_no / no_chunk) %
(no_chunk + 1));
if (chunk >= parity)
@@ -389,21 +398,17 @@ sr_raidp_rw(struct sr_workunit *wu)
lba = phys_offs >> DEV_BSHIFT;
- /* XXX: Big Hammer.. exclude I/O from entire stripe */
+ /* XXX big hammer.. exclude I/O from entire stripe */
if (wu->swu_blk_start == 0)
wu->swu_blk_start = chunk_offs >> DEV_BSHIFT;
wu->swu_blk_end = ((chunk_offs + (no_chunk << strip_bits)) >> DEV_BSHIFT) - 1;
-#if 0
- printf(" : strip=%llx offs=%llx lba=%llx len=%llx n=%lld, "
- "p=%lld\n", strip_no, strip_offs, lba, length, chunk,
- parity);
-#endif
+
scp = sd->sd_vol.sv_chunks[chunk];
if (xs->flags & SCSI_DATA_IN) {
switch (scp->src_meta.scm_status) {
case BIOC_SDONLINE:
case BIOC_SDSCRUB:
- /* Drive is good.. issue single read request */
+ /* drive is good. issue single read request */
if (sr_raidp_addio(wu, chunk, lba, length,
data, xs->flags, 0, NULL))
goto bad;
@@ -412,7 +417,7 @@ sr_raidp_rw(struct sr_workunit *wu)
case BIOC_SDREBUILD:
case BIOC_SDHOTSPARE:
/*
- * XXX: only works if this LBA has already
+ * XXX only works if this LBA has already
* been scrubbed
*/
printf("Disk %llx offline, "
@@ -420,7 +425,7 @@ sr_raidp_rw(struct sr_workunit *wu)
memset(data, 0, length);
for (i = 0; i <= no_chunk; i++) {
/*
- * Read all other drives: xor result
+ * read all other drives: xor result
* into databuffer.
*/
if (i != chunk) {
@@ -437,41 +442,61 @@ sr_raidp_rw(struct sr_workunit *wu)
goto bad;
}
} else {
- /* XXX: handle writes to failed/offline disk?? */
+ /* XXX handle writes to failed/offline disk? */
if (scp->src_meta.scm_status == BIOC_SDOFFLINE)
goto bad;
/*
- * Initialize XORBUF with contents of new data to be
+ * initialize XORBUF with contents of new data to be
* written. This will be XORed with old data and old
* parity in the intr routine. The result in xorbuf
* is the new parity data.
*/
- xorbuf = malloc(length, M_DEVBUF, M_ZERO);
+ xorbuf = sr_get_block(sd, length);
+ if (xorbuf == NULL)
+ goto bad;
memcpy(xorbuf, data, length);
+ /* xor old data */
if (sr_raidp_addio(wu, chunk, lba, length, NULL,
- SCSI_DATA_IN, SR_CCBF_FREEBUF, xorbuf) || /* xor old data */
- sr_raidp_addio(wu, parity, lba, length, NULL,
- SCSI_DATA_IN, SR_CCBF_FREEBUF, xorbuf) || /* xor old parity */
- sr_raidp_addio(wu_w, chunk, lba, length, data,
- xs->flags, 0, NULL) || /* write new data */
- sr_raidp_addio(wu_w, parity, lba, length, xorbuf,
- xs->flags, SR_CCBF_FREEBUF, NULL)) /* write new parity */
+ SCSI_DATA_IN, SR_CCBF_FREEBUF, xorbuf))
+ goto bad;
+
+ /* xor old parity */
+ if (sr_raidp_addio(wu, parity, lba, length, NULL,
+ SCSI_DATA_IN, SR_CCBF_FREEBUF, xorbuf))
+ goto bad;
+
+ /* write new data */
+ if (sr_raidp_addio(wu_w, chunk, lba, length, data,
+ xs->flags, 0, NULL))
+ goto bad;
+
+ /* write new parity */
+ if (sr_raidp_addio(wu_w, parity, lba, length, xorbuf,
+ xs->flags, SR_CCBF_FREEBUF, NULL))
goto bad;
}
- /* Advance to next block */
+ /* advance to next block */
lbaoffs += length;
datalen -= length;
data += length;
}
+
s = splbio();
if (wu_w) {
- /* Collide write request with reads */
+ /* collide write request with reads */
wu_w->swu_blk_start = wu->swu_blk_start;
wu_w->swu_blk_end = wu->swu_blk_end;
+ /*
+ * put xs block in write request (scsi_done not called till
+ * write completes)
+ */
+ wu_w->swu_xs = wu->swu_xs;
+ wu->swu_xs = NULL;
+
wu_w->swu_state = SR_WU_DEFERRED;
wu->swu_collider = wu_w;
TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu_w, swu_link);
@@ -489,10 +514,8 @@ sr_raidp_rw(struct sr_workunit *wu)
if (wu->swu_state == SR_WU_REQUEUE)
goto queued;
- if (sr_check_io_collision(wu)) {
- printf("input collided\n");
+ if (sr_check_io_collision(wu))
goto queued;
- }
start:
sr_raid_startwu(wu);
@@ -516,7 +539,7 @@ sr_raidp_intr(struct buf *bp)
struct sr_softc *sc = sd->sd_sc;
int s, pend;
- DNPRINTF(SR_D_INTR, "%s: sr_intr bp %x xs %x\n",
+ DNPRINTF(SR_D_INTR, "%s: sr_intr bp %p xs %p\n",
DEVNAME(sc), bp, xs);
DNPRINTF(SR_D_INTR, "%s: sr_intr: b_bcount: %d b_resid: %d"
@@ -524,15 +547,6 @@ sr_raidp_intr(struct buf *bp)
ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags,
ccb->ccb_buf.b_blkno, ccb->ccb_target);
-#if 0
- printf("sr_intr: %s %d.%llx %lx %s\n",
- (ccb->ccb_buf.b_flags & B_READ) ? "read" : "write",
- ccb->ccb_target,
- ccb->ccb_buf.b_blkno,
- ccb->ccb_buf.b_bcount,
- ccb->ccb_opaque ? "<xor>" : "");
-#endif
-
s = splbio();
if (ccb->ccb_buf.b_flags & B_ERROR) {
@@ -549,17 +563,17 @@ sr_raidp_intr(struct buf *bp)
} else {
ccb->ccb_state = SR_CCB_OK;
wu->swu_ios_succeeded++;
- if (ccb->ccb_opaque) {
- /* XOR data to result */
+ /* XOR data to result */
+ if (ccb->ccb_opaque)
sr_raidp_xor(ccb->ccb_opaque, ccb->ccb_buf.b_data,
ccb->ccb_buf.b_bcount);
- }
}
- /* Free allocated data buffer */
- if (ccb->ccb_flag & SR_CCBF_FREEBUF)
- free(ccb->ccb_buf.b_data, M_DEVBUF);
-
+ /* free allocated data buffer */
+ if (ccb->ccb_flag & SR_CCBF_FREEBUF) {
+ sr_put_block(sd, ccb->ccb_buf.b_data);
+ ccb->ccb_buf.b_data = NULL;
+ }
wu->swu_ios_complete++;
DNPRINTF(SR_D_INTR, "%s: sr_intr: comp: %d count: %d failed: %d\n",
@@ -567,6 +581,7 @@ sr_raidp_intr(struct buf *bp)
wu->swu_ios_failed);
if (wu->swu_ios_complete >= wu->swu_io_count) {
+
/* if all ios failed, retry reads and give up on writes */
if (wu->swu_ios_failed == wu->swu_ios_complete) {
if (xs->flags & SCSI_DATA_IN) {
@@ -692,9 +707,12 @@ sr_raidp_addio(struct sr_workunit *wu, int dsk, daddr64_t blk, daddr64_t len,
if (!ccb)
return (-1);
- /* Allocate temporary buffer */
- if (data == NULL)
- data = malloc(len, M_DEVBUF, M_ZERO);
+ /* allocate temporary buffer */
+ if (data == NULL) {
+ data = sr_get_block(sd, len);
+ if (data == NULL)
+ return (-1);
+ }
DNPRINTF(0, "%sio: %d.%llx %llx %s\n",
flag & SCSI_DATA_IN ? "read" : "write",
@@ -714,7 +732,7 @@ sr_raidp_addio(struct sr_workunit *wu, int dsk, daddr64_t blk, daddr64_t len,
else
ccb->ccb_buf.b_flags |= B_WRITE;
- /* Add offset for metadata */
+ /* add offset for metadata */
ccb->ccb_buf.b_flags |= B_PHYS;
ccb->ccb_buf.b_blkno = blk;
ccb->ccb_buf.b_bcount = len;
@@ -744,10 +762,11 @@ sr_raidp_addio(struct sr_workunit *wu, int dsk, daddr64_t blk, daddr64_t len,
return (0);
}
-void sr_dump(void *blk, int len)
+void
+sr_dump(void *blk, int len)
{
- uint8_t *b = blk;
- int i, j, c;
+ uint8_t *b = blk;
+ int i, j, c;
for (i = 0; i < len; i += 16) {
for (j = 0; j < 16; j++)
@@ -763,17 +782,17 @@ void sr_dump(void *blk, int len)
}
}
-/* Fast block X0R */
void
sr_raidp_xor(void *a, void *b, int len)
{
- u_int32_t *xa = a, *xb = b;
+ uint32_t *xa = a, *xb = b;
len >>= 2;
while (len--)
*xa++ ^= *xb++;
}
+#if 0
void
sr_raidp_scrub(struct sr_discipline *sd)
{
@@ -800,7 +819,7 @@ sr_raidp_scrub(struct sr_discipline *sd)
parity = no_chunk - ((strip_no / no_chunk) %
(no_chunk + 1));
- xorbuf = malloc(strip_size, M_DEVBUF, M_ZERO);
+ xorbuf = sr_get_block(sd, strip_size);
for (i = 0; i <= no_chunk; i++) {
if (i != parity)
sr_raidp_addio(wu_r, i, 0xBADCAFE, strip_size,
@@ -836,3 +855,17 @@ sr_raidp_scrub(struct sr_discipline *sd)
done:
return;
}
+#endif
+
+void *
+sr_get_block(struct sr_discipline *sd, int length)
+{
+ return malloc(length, M_DEVBUF, M_ZERO | M_NOWAIT | M_CANFAIL);
+}
+
+void
+sr_put_block(struct sr_discipline *sd, void *ptr)
+{
+ free(ptr, M_DEVBUF);
+}
+