#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rf_evenodd_dagfuncs.c,v 1.25 2022/02/16 22:00:56 andvar Exp $");
#include "rf_archs.h"
#ifdef _KERNEL_OPT
#include "opt_raid_diagnostic.h"
#endif
#if RF_INCLUDE_EVENODD > 0
#include <dev/raidframe/raidframevar.h>
#include "rf_raid.h"
#include "rf_dag.h"
#include "rf_dagffrd.h"
#include "rf_dagffwr.h"
#include "rf_dagdegrd.h"
#include "rf_dagdegwr.h"
#include "rf_dagutils.h"
#include "rf_dagfuncs.h"
#include "rf_etimer.h"
#include "rf_general.h"
#include "rf_parityscan.h"
#include "rf_evenodd.h"
#include "rf_evenodd_dagfuncs.h"
RF_RedFuncs_t rf_EOSmallWritePFuncs = {rf_RegularXorFunc, "Regular Old-New P", rf_SimpleXorFunc, "Simple Old-New P"};
RF_RedFuncs_t rf_EOSmallWriteEFuncs = {rf_RegularONEFunc, "Regular Old-New E", rf_SimpleONEFunc, "Regular Old-New E"};
RF_RedFuncs_t rf_eoPRecoveryFuncs = {rf_RecoveryXorFunc, "Recovery Xr", rf_RecoveryXorFunc, "Recovery Xr"};
RF_RedFuncs_t rf_eoERecoveryFuncs = {rf_RecoveryEFunc, "Recovery E Func", rf_RecoveryEFunc, "Recovery E Func"};
void
rf_RegularPEFunc(RF_DagNode_t *node)
{
rf_RegularESubroutine(node, node->results[1]);
rf_RegularXorFunc(node);
}
void
rf_RegularONEFunc(RF_DagNode_t *node)
{
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
int EpdaIndex = (node->numParams - 1) / 2 - 1;
int i, k;
int suoffset, length;
RF_RowCol_t scol;
char *srcbuf, *destbuf;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_Etimer_t timer;
RF_PhysDiskAddr_t *pda;
#ifdef RAID_DIAGNOSTIC
RF_PhysDiskAddr_t *EPDA =
(RF_PhysDiskAddr_t *) node->params[EpdaIndex].p;
int ESUOffset = rf_StripeUnitOffset(layoutPtr, EPDA->startSector);
RF_ASSERT(EPDA->type == RF_PDA_TYPE_Q);
RF_ASSERT(ESUOffset == 0);
#endif
RF_ETIMER_START(timer);
for (k = 0; k < EpdaIndex; k += 2) {
length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *) node->params[k].p)->numSector);
rf_bxor(node->params[k + EpdaIndex + 3].p, node->params[k + 1].p, length);
}
for (i = 0; i < EpdaIndex; i += 2)
if (node->params[i + 1].p != node->results[0]) {
pda = (RF_PhysDiskAddr_t *) node->params[i].p;
srcbuf = (char *) node->params[i + 1].p;
scol = rf_EUCol(layoutPtr, pda->raidAddress);
suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
destbuf = ((char *) node->results[0]) + rf_RaidAddressToByte(raidPtr, suoffset);
rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
}
for (k = 0; k < EpdaIndex; k += 2) {
length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *) node->params[k].p)->numSector);
rf_bxor(node->params[k + EpdaIndex + 3].p, node->params[k + 1].p, length);
}
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
tracerec->q_us += RF_ETIMER_VAL_US(timer);
rf_GenericWakeupFunc(node, 0);
}
void
rf_SimpleONEFunc(RF_DagNode_t *node)
{
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *) node->params[0].p;
int retcode = 0;
char *srcbuf, *destbuf;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
int length;
RF_RowCol_t scol;
RF_Etimer_t timer;
RF_ASSERT(((RF_PhysDiskAddr_t *) node->params[2].p)->type == RF_PDA_TYPE_Q);
if (node->dagHdr->status == rf_enable) {
RF_ETIMER_START(timer);
length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *) node->params[4].p)->numSector);
retcode = rf_bxor(node->params[5].p, node->params[1].p, length);
scol = rf_EUCol(layoutPtr, pda->raidAddress);
srcbuf = node->params[1].p;
destbuf = node->params[3].p;
rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
rf_bxor(node->params[5].p, node->params[1].p, length);
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
tracerec->q_us += RF_ETIMER_VAL_US(timer);
}
rf_GenericWakeupFunc(node, retcode);
}
void
rf_RegularESubroutine(RF_DagNode_t *node, char *ebuf)
{
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
RF_PhysDiskAddr_t *pda;
int i, suoffset;
RF_RowCol_t scol;
char *srcbuf, *destbuf;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_Etimer_t timer;
RF_ETIMER_START(timer);
for (i = 0; i < node->numParams - 2; i += 2) {
RF_ASSERT(node->params[i + 1].p != ebuf);
pda = (RF_PhysDiskAddr_t *) node->params[i].p;
suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
scol = rf_EUCol(layoutPtr, pda->raidAddress);
srcbuf = (char *) node->params[i + 1].p;
destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset);
rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
}
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
tracerec->xor_us += RF_ETIMER_VAL_US(timer);
}
void
rf_RegularEFunc(RF_DagNode_t *node)
{
rf_RegularESubroutine(node, node->results[0]);
rf_GenericWakeupFunc(node, 0);
}
void
rf_DegrESubroutine(RF_DagNode_t *node, char *ebuf)
{
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
RF_PhysDiskAddr_t *failedPDA = (RF_PhysDiskAddr_t *) node->params[node->numParams - 2].p;
RF_PhysDiskAddr_t *pda;
int i, suoffset, failedSUOffset = rf_StripeUnitOffset(layoutPtr, failedPDA->startSector);
RF_RowCol_t scol;
char *srcbuf, *destbuf;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_Etimer_t timer;
RF_ETIMER_START(timer);
for (i = 0; i < node->numParams - 2; i += 2) {
RF_ASSERT(node->params[i + 1].p != ebuf);
pda = (RF_PhysDiskAddr_t *) node->params[i].p;
suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
scol = rf_EUCol(layoutPtr, pda->raidAddress);
srcbuf = (char *) node->params[i + 1].p;
destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset - failedSUOffset);
rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
}
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
tracerec->q_us += RF_ETIMER_VAL_US(timer);
}
void
rf_Degraded_100_EOFunc(RF_DagNode_t *node)
{
rf_DegrESubroutine(node, node->results[1]);
rf_RecoveryXorFunc(node);
}
void
rf_e_EncOneSect(
RF_RowCol_t srcLogicCol,
char *srcSecbuf,
RF_RowCol_t destLogicCol,
char *destSecbuf,
int bytesPerSector)
{
int S_index;
int numRowInEncMatix = (RF_EO_MATRIX_DIM) - 1;
RF_RowCol_t j, indexInDest,
indexInSrc;
int bytesPerEU = bytesPerSector / numRowInEncMatix;
#if RF_EO_MATRIX_DIM > 17
int shortsPerEU = bytesPerEU / sizeof(short);
short *destShortBuf, *srcShortBuf1, *srcShortBuf2;
short temp1;
#elif RF_EO_MATRIX_DIM == 17
int longsPerEU = bytesPerEU / sizeof(long);
long *destLongBuf, *srcLongBuf1, *srcLongBuf2;
long temp1;
#endif
#if RF_EO_MATRIX_DIM > 17
RF_ASSERT(sizeof(short) == 2 || sizeof(short) == 1);
RF_ASSERT(bytesPerEU % sizeof(short) == 0);
#elif RF_EO_MATRIX_DIM == 17
RF_ASSERT(sizeof(long) == 8 || sizeof(long) == 4);
RF_ASSERT(bytesPerEU % sizeof(long) == 0);
#endif
S_index = rf_EO_Mod((RF_EO_MATRIX_DIM - 1 + destLogicCol - srcLogicCol), RF_EO_MATRIX_DIM);
#if RF_EO_MATRIX_DIM > 17
srcShortBuf1 = (short *) (srcSecbuf + S_index * bytesPerEU);
#elif RF_EO_MATRIX_DIM == 17
srcLongBuf1 = (long *) (srcSecbuf + S_index * bytesPerEU);
#endif
for (indexInDest = 0; indexInDest < numRowInEncMatix; indexInDest++) {
indexInSrc = rf_EO_Mod((indexInDest + destLogicCol - srcLogicCol), RF_EO_MATRIX_DIM);
#if RF_EO_MATRIX_DIM > 17
destShortBuf = (short *) (destSecbuf + indexInDest * bytesPerEU);
srcShortBuf2 = (short *) (srcSecbuf + indexInSrc * bytesPerEU);
for (j = 0; j < shortsPerEU; j++) {
temp1 = destShortBuf[j] ^ srcShortBuf1[j];
if (indexInSrc != RF_EO_MATRIX_DIM - 1)
destShortBuf[j] = (srcShortBuf2[j]) ^ temp1;
else
destShortBuf[j] = temp1;
}
#elif RF_EO_MATRIX_DIM == 17
destLongBuf = (long *) (destSecbuf + indexInDest * bytesPerEU);
srcLongBuf2 = (long *) (srcSecbuf + indexInSrc * bytesPerEU);
for (j = 0; j < longsPerEU; j++) {
temp1 = destLongBuf[j] ^ srcLongBuf1[j];
if (indexInSrc != RF_EO_MATRIX_DIM - 1)
destLongBuf[j] = (srcLongBuf2[j]) ^ temp1;
else
destLongBuf[j] = temp1;
}
#endif
}
}
void
rf_e_encToBuf(
RF_Raid_t * raidPtr,
RF_RowCol_t srcLogicCol,
char *srcbuf,
RF_RowCol_t destLogicCol,
char *destbuf,
int numSector)
{
int i, bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
for (i = 0; i < numSector; i++) {
rf_e_EncOneSect(srcLogicCol, srcbuf, destLogicCol, destbuf, bytesPerSector);
srcbuf += bytesPerSector;
destbuf += bytesPerSector;
}
}
void
rf_RecoveryEFunc(RF_DagNode_t *node)
{
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
RF_PhysDiskAddr_t *failedPDA = (RF_PhysDiskAddr_t *) node->params[node->numParams - 2].p;
RF_RowCol_t scol,
fcol = rf_EUCol(layoutPtr, failedPDA->raidAddress);
int i;
RF_PhysDiskAddr_t *pda;
int suoffset, failedSUOffset = rf_StripeUnitOffset(layoutPtr, failedPDA->startSector);
char *srcbuf, *destbuf;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_Etimer_t timer;
memset(node->results[0], 0,
rf_RaidAddressToByte(raidPtr, failedPDA->numSector));
if (node->dagHdr->status == rf_enable) {
RF_ETIMER_START(timer);
for (i = 0; i < node->numParams - 2; i += 2)
if (node->params[i + 1].p != node->results[0]) {
pda = (RF_PhysDiskAddr_t *) node->params[i].p;
if (i == node->numParams - 4)
scol = RF_EO_MATRIX_DIM - 2;
else
scol = rf_EUCol(layoutPtr, pda->raidAddress);
srcbuf = (char *) node->params[i + 1].p;
suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
destbuf = ((char *) node->results[0]) + rf_RaidAddressToByte(raidPtr, suoffset - failedSUOffset);
rf_e_encToBuf(raidPtr, scol, srcbuf, fcol, destbuf, pda->numSector);
}
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
tracerec->xor_us += RF_ETIMER_VAL_US(timer);
}
rf_GenericWakeupFunc(node, 0);
}
void
rf_EO_DegradedWriteEFunc(RF_DagNode_t * node)
{
rf_DegrESubroutine(node, node->results[0]);
rf_GenericWakeupFunc(node, 0);
}
void
rf_doubleEOdecode(
RF_Raid_t * raidPtr,
char **rrdbuf,
char **dest,
RF_RowCol_t * fcol,
char *pbuf,
char *ebuf)
{
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & (raidPtr->Layout);
int i, j, k, f1, f2, row;
int rrdrow, erow, count = 0;
int bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
int numRowInEncMatix = (RF_EO_MATRIX_DIM) - 1;
#if 0
int pcol = (RF_EO_MATRIX_DIM) - 1;
#endif
int ecol = (RF_EO_MATRIX_DIM) - 2;
int bytesPerEU = bytesPerSector / numRowInEncMatix;
int numDataCol = layoutPtr->numDataCol;
#if RF_EO_MATRIX_DIM > 17
int shortsPerEU = bytesPerEU / sizeof(short);
short *rrdbuf_current, *pbuf_current, *ebuf_current;
short *dest_smaller, *dest_smaller_current, *dest_larger, *dest_larger_current;
short *temp;
short *P;
RF_ASSERT(bytesPerEU % sizeof(short) == 0);
#elif RF_EO_MATRIX_DIM == 17
int longsPerEU = bytesPerEU / sizeof(long);
long *rrdbuf_current, *pbuf_current, *ebuf_current;
long *dest_smaller, *dest_smaller_current, *dest_larger, *dest_larger_current;
long *temp;
long *P;
RF_ASSERT(bytesPerEU % sizeof(long) == 0);
#endif
P = RF_Malloc(bytesPerEU);
temp = RF_Malloc(bytesPerEU);
RF_ASSERT(*((long *) dest[0]) == 0);
RF_ASSERT(*((long *) dest[1]) == 0);
RF_ASSERT(*P == 0);
for (i = 0; i < numRowInEncMatix; i++)
for (k = 0; k < longsPerEU; k++) {
#if RF_EO_MATRIX_DIM > 17
ebuf_current = ((short *) ebuf) + i * shortsPerEU + k;
pbuf_current = ((short *) pbuf) + i * shortsPerEU + k;
#elif RF_EO_MATRIX_DIM == 17
ebuf_current = ((long *) ebuf) + i * longsPerEU + k;
pbuf_current = ((long *) pbuf) + i * longsPerEU + k;
#endif
P[k] ^= *ebuf_current;
P[k] ^= *pbuf_current;
}
RF_ASSERT(fcol[0] != fcol[1]);
if (fcol[0] < fcol[1]) {
#if RF_EO_MATRIX_DIM > 17
dest_smaller = (short *) (dest[0]);
dest_larger = (short *) (dest[1]);
#elif RF_EO_MATRIX_DIM == 17
dest_smaller = (long *) (dest[0]);
dest_larger = (long *) (dest[1]);
#endif
f1 = fcol[0];
f2 = fcol[1];
} else {
#if RF_EO_MATRIX_DIM > 17
dest_smaller = (short *) (dest[1]);
dest_larger = (short *) (dest[0]);
#elif RF_EO_MATRIX_DIM == 17
dest_smaller = (long *) (dest[1]);
dest_larger = (long *) (dest[0]);
#endif
f1 = fcol[1];
f2 = fcol[0];
}
row = (RF_EO_MATRIX_DIM) - 1;
while ((row = rf_EO_Mod((row + f1 - f2), RF_EO_MATRIX_DIM)) != ((RF_EO_MATRIX_DIM) - 1)) {
#if RF_EO_MATRIX_DIM > 17
dest_larger_current = dest_larger + row * shortsPerEU;
dest_smaller_current = dest_smaller + row * shortsPerEU;
#elif RF_EO_MATRIX_DIM == 17
dest_larger_current = dest_larger + row * longsPerEU;
dest_smaller_current = dest_smaller + row * longsPerEU;
#endif
for (j = 0; j < numDataCol; j++) {
if (j == f1 || j == f2)
continue;
rrdrow = rf_EO_Mod((row + f2 - j), RF_EO_MATRIX_DIM);
if (rrdrow != (RF_EO_MATRIX_DIM) - 1) {
#if RF_EO_MATRIX_DIM > 17
rrdbuf_current = (short *) (rrdbuf[j]) + rrdrow * shortsPerEU;
for (k = 0; k < shortsPerEU; k++)
temp[k] ^= *(rrdbuf_current + k);
#elif RF_EO_MATRIX_DIM == 17
rrdbuf_current = (long *) (rrdbuf[j]) + rrdrow * longsPerEU;
for (k = 0; k < longsPerEU; k++)
temp[k] ^= *(rrdbuf_current + k);
#endif
}
}
erow = rf_EO_Mod((row + f2 - ecol), (RF_EO_MATRIX_DIM));
if (erow != (RF_EO_MATRIX_DIM) - 1) {
#if RF_EO_MATRIX_DIM > 17
ebuf_current = (short *) ebuf + shortsPerEU * erow;
for (k = 0; k < shortsPerEU; k++)
temp[k] ^= *(ebuf_current + k);
#elif RF_EO_MATRIX_DIM == 17
ebuf_current = (long *) ebuf + longsPerEU * erow;
for (k = 0; k < longsPerEU; k++)
temp[k] ^= *(ebuf_current + k);
#endif
}
#if RF_EO_MATRIX_DIM > 17
for (k = 0; k < shortsPerEU; k++)
temp[k] ^= P[k];
for (k = 0; k < shortsPerEU; k++)
dest_larger_current[k] = temp[k];
#elif RF_EO_MATRIX_DIM == 17
for (k = 0; k < longsPerEU; k++)
temp[k] ^= P[k];
for (k = 0; k < longsPerEU; k++)
dest_larger_current[k] = temp[k];
#endif
for (j = 0; j < numDataCol; j++) {
if (j == f1 || j == f2)
continue;
#if RF_EO_MATRIX_DIM > 17
rrdbuf_current = (short *) (rrdbuf[j]) + row * shortsPerEU;
for (k = 0; k < shortsPerEU; k++)
temp[k] ^= *(rrdbuf_current + k);
#elif RF_EO_MATRIX_DIM == 17
rrdbuf_current = (long *) (rrdbuf[j]) + row * longsPerEU;
for (k = 0; k < longsPerEU; k++)
temp[k] ^= *(rrdbuf_current + k);
#endif
}
#if RF_EO_MATRIX_DIM > 17
pbuf_current = (short *) pbuf + shortsPerEU * row;
for (k = 0; k < shortsPerEU; k++)
temp[k] ^= *(pbuf_current + k);
for (k = 0; k < shortsPerEU; k++)
dest_smaller_current[k] = temp[k];
#elif RF_EO_MATRIX_DIM == 17
pbuf_current = (long *) pbuf + longsPerEU * row;
for (k = 0; k < longsPerEU; k++)
temp[k] ^= *(pbuf_current + k);
for (k = 0; k < longsPerEU; k++)
dest_smaller_current[k] = temp[k];
#endif
count++;
}
RF_ASSERT(count == numRowInEncMatix);
RF_Free((char *) P, bytesPerEU);
RF_Free((char *) temp, bytesPerEU);
}
void
rf_EvenOddDoubleRecoveryFunc(RF_DagNode_t *node)
{
int ndataParam = 0;
int np = node->numParams;
RF_AccessStripeMap_t *asmap = (RF_AccessStripeMap_t *) node->params[np - 1].p;
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np - 2].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & (raidPtr->Layout);
int i, prm, sector, nresults = node->numResults;
RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit;
unsigned sosAddr;
int mallc_one = 0, mallc_two = 0;
int bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
RF_PhysDiskAddr_t *ppda, *ppda2, *epda, *epda2, *pda, *pda0, *pda1,
npda;
RF_RowCol_t fcol[2], fsuoff[2], fsuend[2], numDataCol = layoutPtr->numDataCol;
char **buf, *ebuf, *pbuf, *dest[2];
long *suoff = NULL, *suend = NULL, *prmToCol = NULL,
psuoff = 0, esuoff = 0;
RF_SectorNum_t startSector, endSector;
RF_Etimer_t timer;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_ETIMER_START(timer);
for (i = 0; i <= np; i++)
if (((RF_PhysDiskAddr_t *) node->params[i].p)->type != RF_PDA_TYPE_DATA) {
ndataParam = i;
break;
}
buf = RF_Malloc(numDataCol * sizeof(*buf));
if (ndataParam != 0) {
suoff = RF_Malloc(ndataParam * sizeof(*suoff));
suend = RF_Malloc(ndataParam * sizeof(*suend));
prmToCol = RF_Malloc(ndataParam * sizeof(*prmToCol));
}
if (asmap->failedPDAs[1] &&
(asmap->failedPDAs[1]->numSector + asmap->failedPDAs[0]->numSector < secPerSU)) {
RF_ASSERT(0);
ppda = node->params[np - 6].p;
ppda2 = node->params[np - 5].p;
RF_ASSERT(ppda2->type == RF_PDA_TYPE_PARITY);
epda = node->params[np - 4].p;
epda2 = node->params[np - 3].p;
RF_ASSERT(epda2->type == RF_PDA_TYPE_Q);
} else {
ppda = node->params[np - 4].p;
epda = node->params[np - 3].p;
psuoff = rf_StripeUnitOffset(layoutPtr, ppda->startSector);
esuoff = rf_StripeUnitOffset(layoutPtr, epda->startSector);
RF_ASSERT(psuoff == esuoff);
}
if (nresults == 1) {
pda = node->results[0];
memset(pda->bufPtr, 0, bytesPerSector * pda->numSector);
fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda->startSector);
fsuend[0] = fsuoff[0] + pda->numSector;
fsuoff[1] = 0;
fsuend[1] = 0;
startSector = fsuoff[0];
endSector = fsuend[0];
fcol[0] = rf_EUCol(layoutPtr, pda->raidAddress);
sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress);
for (i = 0; i < numDataCol; i++) {
npda.raidAddress = sosAddr + (i * secPerSU);
(raidPtr->Layout.map->MapSector) (raidPtr, npda.raidAddress, &(npda.col), &(npda.startSector), 0);
if (RF_DEAD_DISK(raidPtr->Disks[npda.col].status))
if (i != fcol[0])
break;
}
RF_ASSERT(i < numDataCol);
fcol[1] = i;
} else {
RF_ASSERT(nresults == 2);
pda0 = node->results[0];
memset(pda0->bufPtr, 0, bytesPerSector * pda0->numSector);
pda1 = node->results[1];
memset(pda1->bufPtr, 0, bytesPerSector * pda1->numSector);
fcol[0] = rf_EUCol(layoutPtr, pda0->raidAddress);
fcol[1] = rf_EUCol(layoutPtr, pda1->raidAddress);
fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda0->startSector);
fsuend[0] = fsuoff[0] + pda0->numSector;
fsuoff[1] = rf_StripeUnitOffset(layoutPtr, pda1->startSector);
fsuend[1] = fsuoff[1] + pda1->numSector;
startSector = RF_MIN(pda0->startSector, pda1->startSector);
endSector = RF_MAX(fsuend[0], fsuend[1]);
}
for (prm = 0; prm < ndataParam; prm++) {
pda = node->params[prm].p;
suoff[prm] = rf_StripeUnitOffset(layoutPtr, pda->startSector);
suend[prm] = suoff[prm] + pda->numSector;
prmToCol[prm] = rf_EUCol(layoutPtr, pda->raidAddress);
}
for (sector = startSector; sector < endSector; sector++) {
if (nresults == 2)
if (!(fsuoff[0] <= sector && sector < fsuend[0]) && !(fsuoff[1] <= sector && sector < fsuend[1]))
continue;
for (prm = 0; prm < ndataParam; prm++)
if (suoff[prm] <= sector && sector < suend[prm])
buf[(prmToCol[prm])] = (char *)((RF_PhysDiskAddr_t *) node->params[prm].p)->bufPtr +
rf_RaidAddressToByte(raidPtr, sector - suoff[prm]);
RF_ASSERT(nresults == 1 || nresults == 2);
if (nresults == 1) {
dest[0] = (char *)((RF_PhysDiskAddr_t *) node->results[0])->bufPtr + rf_RaidAddressToByte(raidPtr, sector - fsuoff[0]);
dest[1] = RF_Malloc(bytesPerSector);
mallc_two = 1;
} else {
if (fsuoff[0] <= sector && sector < fsuend[0])
dest[0] = (char *)((RF_PhysDiskAddr_t *) node->results[0])->bufPtr + rf_RaidAddressToByte(raidPtr, sector - fsuoff[0]);
else {
dest[0] = RF_Malloc(bytesPerSector);
mallc_one = 1;
}
if (fsuoff[1] <= sector && sector < fsuend[1])
dest[1] = (char *)((RF_PhysDiskAddr_t *) node->results[1])->bufPtr + rf_RaidAddressToByte(raidPtr, sector - fsuoff[1]);
else {
dest[1] = RF_Malloc(bytesPerSector);
mallc_two = 1;
}
RF_ASSERT(mallc_one == 0 || mallc_two == 0);
}
pbuf = (char *)ppda->bufPtr + rf_RaidAddressToByte(raidPtr, sector - psuoff);
ebuf = (char *)epda->bufPtr + rf_RaidAddressToByte(raidPtr, sector - esuoff);
rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf);
if (mallc_one == 1)
RF_Free(dest[0], bytesPerSector);
if (mallc_two == 1)
RF_Free(dest[1], bytesPerSector);
mallc_one = mallc_two = 0;
}
RF_Free(buf, numDataCol * sizeof(char *));
if (ndataParam != 0) {
RF_Free(suoff, ndataParam * sizeof(long));
RF_Free(suend, ndataParam * sizeof(long));
RF_Free(prmToCol, ndataParam * sizeof(long));
}
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
if (tracerec) {
tracerec->q_us += RF_ETIMER_VAL_US(timer);
}
rf_GenericWakeupFunc(node, 0);
}
void
rf_EOWriteDoubleRecoveryFunc(RF_DagNode_t *node)
{
int np = node->numParams;
RF_AccessStripeMap_t *asmap = (RF_AccessStripeMap_t *) node->params[np - 1].p;
RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np - 2].p;
RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & (raidPtr->Layout);
RF_SectorNum_t sector;
RF_RowCol_t col, scol;
int prm, i, j;
RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit;
unsigned sosAddr;
unsigned bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
RF_int64 numbytes;
RF_SectorNum_t startSector, endSector;
RF_PhysDiskAddr_t *ppda, *epda, *pda, *fpda, npda;
RF_RowCol_t fcol[2], numDataCol = layoutPtr->numDataCol;
char **buf;
char *ebuf, *pbuf, *dest[2], *olddata[2];
RF_Etimer_t timer;
RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
RF_ASSERT(asmap->numDataFailed == 1);
RF_ETIMER_START(timer);
buf = RF_Malloc(numDataCol * sizeof(*buf));
ppda = node->results[0];
epda = node->results[1];
fpda = asmap->failedPDAs[0];
startSector = rf_StripeUnitOffset(layoutPtr, fpda->startSector);
endSector = startSector + fpda->numSector;
for (prm = 0; prm < numDataCol - 2; prm++) {
pda = (RF_PhysDiskAddr_t *) node->params[prm].p;
col = rf_EUCol(layoutPtr, pda->raidAddress);
buf[col] = pda->bufPtr;
}
pbuf = ppda->bufPtr;
ebuf = epda->bufPtr;
fcol[0] = rf_EUCol(layoutPtr, fpda->raidAddress);
sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress);
for (i = 0; i < numDataCol; i++) {
npda.raidAddress = sosAddr + (i * secPerSU);
(raidPtr->Layout.map->MapSector) (raidPtr, npda.raidAddress, &(npda.col), &(npda.startSector), 0);
if (RF_DEAD_DISK(raidPtr->Disks[npda.col].status))
if (i != fcol[0])
break;
}
RF_ASSERT(i < numDataCol);
fcol[1] = i;
numbytes = fpda->numSector * bytesPerSector;
olddata[0] = RF_Malloc(numbytes);
olddata[1] = RF_Malloc(numbytes);
dest[0] = olddata[0];
dest[1] = olddata[1];
for (sector = startSector, i = 0; sector < endSector; sector++, i++) {
rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf);
for (j = 0; j < numDataCol; j++)
if ((j != fcol[0]) && (j != fcol[1]))
buf[j] += bytesPerSector;
dest[0] += bytesPerSector;
dest[1] += bytesPerSector;
ebuf += bytesPerSector;
pbuf += bytesPerSector;
}
rf_bxor(((RF_PhysDiskAddr_t *) node->params[numDataCol].p)->bufPtr, olddata[0], numbytes);
scol = rf_EUCol(layoutPtr, fpda->raidAddress);
rf_e_encToBuf(raidPtr, scol, olddata[0], RF_EO_MATRIX_DIM - 2, epda->bufPtr, fpda->numSector);
rf_bxor(olddata[0], ppda->bufPtr, numbytes);
RF_Free(olddata[0], numbytes);
RF_Free(olddata[1], numbytes);
RF_Free(buf, numDataCol * sizeof(char *));
RF_ETIMER_STOP(timer);
RF_ETIMER_EVAL(timer);
if (tracerec) {
tracerec->q_us += RF_ETIMER_VAL_US(timer);
}
rf_GenericWakeupFunc(node, 0);
}
#endif