diff options
author | Jordan Hargrave <jordan@cvs.openbsd.org> | 2009-06-17 22:45:42 +0000 |
---|---|---|
committer | Jordan Hargrave <jordan@cvs.openbsd.org> | 2009-06-17 22:45:42 +0000 |
commit | 89ae8a19aa82210ba492f252aca8b5db868ce984 (patch) | |
tree | 4ed8d6fd89a8d5c5d9df432d52ad090555db5435 | |
parent | 851100dc32d2b98d73cd416c018ed5ef8f653c57 (diff) |
Added openings callback; cleanup & KNF
I/O now works reliably
ok marco@
-rw-r--r-- | sys/dev/softraid_raidp.c | 169 |
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); +} + |