summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2010-02-04 07:30:28 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2010-02-04 07:30:28 +0000
commit1df3c7c0cccb12a30905c73411a17ebd654eb87b (patch)
tree2a65f2b7866b21b2b3382fb6485db54501da4ff9 /sys/dev
parent4e5d420eeb9c6e11db51487b993a46e84a0c8752 (diff)
Added optimization for XY reads, requires only one temp buffer
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/softraid_raid6.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/sys/dev/softraid_raid6.c b/sys/dev/softraid_raid6.c
index 21518c75516..0287d0dc0e0 100644
--- a/sys/dev/softraid_raid6.c
+++ b/sys/dev/softraid_raid6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_raid6.c,v 1.13 2010/02/04 03:34:05 jordan Exp $ */
+/* $OpenBSD: softraid_raid6.c,v 1.14 2010/02/04 07:30:27 jordan Exp $ */
/*
* Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2009 Jordan Hargrave <jordan@openbsd.org>
@@ -76,6 +76,7 @@ void sr_put_block(struct sr_discipline *, void *);
void gf_init(void);
uint8_t gf_inv(uint8_t);
int gf_premul(uint8_t);
+uint8_t gf_mul(uint8_t, uint8_t);
#define SR_NOFAIL 0x00
#define SR_FAILX (1L << 0)
@@ -457,7 +458,7 @@ sr_raid6_rw(struct sr_workunit *wu)
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
struct sr_chunk *scp;
- int s, fail, i, rwmode;
+ int s, fail, i, rwmode, gxinv;
daddr64_t blk, lbaoffs, strip_no, chunk, qchunk, pchunk, fchunk;
daddr64_t strip_size, no_chunk, lba, chunk_offs, phys_offs;
daddr64_t strip_bits, length, strip_offs, datalen, row_size;
@@ -550,11 +551,13 @@ sr_raid6_rw(struct sr_workunit *wu)
printf("Disk %llx offline, "
"regenerating Dx+P\n", chunk);
+ gxinv = gf_inv(gf_pow[chunk]);
+
/* Calculate: Dx = (Q^Dz*gz)*inv(gx) */
memset(data, 0, length);
if (sr_raid6_addio(wu, qchunk, lba, length, NULL,
SCSI_DATA_IN, SR_CCBF_FREEBUF, NULL, data,
- gf_inv(gf_pow[chunk])))
+ gxinv))
goto bad;
/* Read Dz * gz * inv(gx) */
@@ -565,7 +568,7 @@ sr_raid6_rw(struct sr_workunit *wu)
if (sr_raid6_addio(wu, i, lba,
length, NULL, SCSI_DATA_IN,
SR_CCBF_FREEBUF, NULL,
- data, gf_pow[i+255-chunk]))
+ data, gf_mul(gf_pow[i], gxinv)))
goto bad;
}
@@ -574,43 +577,44 @@ sr_raid6_rw(struct sr_workunit *wu)
/* Dx, Dy failed */
printf("Disk %llx & %llx offline, "
"regenerating Dx+Dy\n", chunk, fchunk);
- qbuf = sr_get_block(sd, length);
- if (qbuf == NULL)
- goto bad;
pbuf = sr_get_block(sd, length);
if (pbuf == NULL)
goto bad;
+ gxinv = gf_inv(gf_pow[chunk] ^ gf_pow[fchunk]);
+
+ /* read Q * inv(gx + gy) */
+ memset(data, 0, length);
+ if (sr_raid6_addio(wu, qchunk, lba,
+ length, NULL, SCSI_DATA_IN,
+ SR_CCBF_FREEBUF, NULL,
+ data, gxinv))
+ goto bad;
+
+ /* read P */
+ if (sr_raid6_addio(wu, pchunk, lba,
+ length, NULL, SCSI_DATA_IN,
+ SR_CCBF_FREEBUF, pbuf,
+ NULL, 0))
+ goto bad;
+
/* Calculate: Dx*gx^Dy*gy = Q^(Dz*gz) ; Dx^Dy = P^Dz
* Q: sr_raid6_xorp(qbuf, --, length);
* P: sr_raid6_xorp(pbuf, --, length);
* Dz: sr_raid6_xorp(pbuf, --, length);
* sr_raid6_xorq(qbuf, --, length, gf_pow[i]);
*/
- memset(data, 0, length);
for (i = 0; i < no_chunk+2; i++) {
- if (i == qchunk) {
- /* read Q */
- if (sr_raid6_addio(wu, i, lba,
- length, NULL, SCSI_DATA_IN,
- SR_CCBF_FREEBUF, qbuf,
- NULL, 0))
- goto bad;
- } else if (i == pchunk) {
- /* read P */
- if (sr_raid6_addio(wu, i, lba,
- length, NULL, SCSI_DATA_IN,
- SR_CCBF_FREEBUF, pbuf,
- NULL, 0))
- goto bad;
- } else if (i != chunk) {
- /* read Dz * gz */
- if (sr_raid6_addio(wu, i, lba,
- length, NULL, SCSI_DATA_IN,
- SR_CCBF_FREEBUF, pbuf,
- qbuf, gf_pow[i]))
- goto bad;
- }
+ if (i == qchunk || i == pchunk ||
+ i == chunk || i == fchunk)
+ continue;
+
+ /* read Dz * gz */
+ if (sr_raid6_addio(wu, i, lba,
+ length, NULL, SCSI_DATA_IN,
+ SR_CCBF_FREEBUF, pbuf,
+ data, gf_mul(gf_pow[i], gxinv)))
+ goto bad;
}
/* run fake wu when read i/o is complete */
@@ -621,11 +625,7 @@ sr_raid6_rw(struct sr_workunit *wu)
wu_w->swu_flags |= SR_WUF_FAIL;
if (sr_raid6_addio(wu_w, 0, 0, length, pbuf, 0,
SR_CCBF_FREEBUF, NULL, data,
- gf_inv(gf_pow[255+chunk-fchunk] ^ 1)))
- goto bad;
- if (sr_raid6_addio(wu_w, 0, 0, length, qbuf, 0,
- SR_CCBF_FREEBUF, NULL, data,
- gf_inv(gf_pow[chunk] ^ gf_pow[fchunk])))
+ gf_mul(gf_pow[fchunk], gxinv)))
goto bad;
} else {
/* Two cases: single disk (Dx) or (Dx+Q)
@@ -1081,6 +1081,12 @@ gf_inv(uint8_t a)
return gf_pow[255 - gf_log[a]];
}
+uint8_t
+gf_mul(uint8_t a, uint8_t b)
+{
+ return gf_pow[gf_log[a] + gf_log[b]];
+}
+
/* Precalculate multiplication tables for drive gn */
int
gf_premul(uint8_t gn)