unmap->addr[2] = dma_map_page(dev, dest, d_off,
len, DMA_BIDIRECTIONAL);
unmap->bidi_cnt = 1; /* engine only looks at Q, but expects it to follow P */
pq[1] = unmap->addr[2];
/* this looks funny, but the engine looks for Q at *dma_dest[1]andignoresdma_dest[0]asadest *duetoDMA_PREP_PQ_DISABLE_P
*/
tx = dma->device_prep_dma_pq(chan, dma_dest, unmap->addr, 1, &coef, len, dma_flags);
/* could not get a descriptor, unmap and fall through to *thesynchronouspath
*/
dmaengine_unmap_put(unmap);
}
/* no channel available, or failed to allocate a descriptor, so *performtheoperationsynchronously
*/
async_tx_quiesce(&submit->depend_tx);
qmul = raid6_gfmul[coef];
d = page_address(dest) + d_off;
s = page_address(src) + s_off;
good_srcs = 0;
good = -1; for (i = 0; i < disks-2; i++) { if (blocks[i] == NULL) continue; if (i == faila || i == failb) continue;
good = i;
good_srcs++;
}
BUG_ON(good_srcs > 1);
p = blocks[disks-2];
p_off = offs[disks-2];
q = blocks[disks-1];
q_off = offs[disks-1];
g = blocks[good];
g_off = offs[good];
/* Compute syndrome with zero for the missing data pages *Usethedeaddatapagesastemporarystoragefordeltapand *deltaq
*/
dp = blocks[faila];
dp_off = offs[faila];
dq = blocks[failb];
dq_off = offs[failb];
/* if a dma resource is not available or a scribble buffer is not *availablepunttothesynchronouspath.Inthe'dmanot *available'casebesuretousethescribblebufferto *preservethecontentof'blocks'asthecallerintended.
*/ if (!async_dma_find_channel(DMA_PQ) || !scribble) { void **ptrs = scribble ? scribble : (void **) blocks;
async_tx_quiesce(&submit->depend_tx); for (i = 0; i < disks; i++) if (blocks[i] == NULL)
ptrs[i] = raid6_get_zero_page(); else
ptrs[i] = page_address(blocks[i]) + offs[i];
non_zero_srcs = 0; for (i = 0; i < disks-2 && non_zero_srcs < 4; i++) if (blocks[i])
non_zero_srcs++; switch (non_zero_srcs) { case0: case1: /* There must be at least 2 sources - the failed devices. */
BUG();
case2: /* dma devices do not uniformly understand a zero source pq *operation(incontrasttothesynchronouscase),so *explicitlyhandlethespecialcaseofa4diskarraywith *bothdatadisksmissing.
*/ return __2data_recov_4(disks, bytes, faila, failb,
blocks, offs, submit); case3: /* dma devices do not uniformly understand a single *sourcepqoperation(incontrasttothesynchronous *case),soexplicitlyhandlethespecialcaseofa5disk *arraywith2of3datadisksmissing.
*/ return __2data_recov_5(disks, bytes, faila, failb,
blocks, offs, submit); default: return __2data_recov_n(disks, bytes, faila, failb,
blocks, offs, submit);
}
}
EXPORT_SYMBOL_GPL(async_raid6_2data_recov);
/* if a dma resource is not available or a scribble buffer is not *availablepunttothesynchronouspath.Inthe'dmanot *available'casebesuretousethescribblebufferto *preservethecontentof'blocks'asthecallerintended.
*/ if (!async_dma_find_channel(DMA_PQ) || !scribble) { void **ptrs = scribble ? scribble : (void **) blocks;
async_tx_quiesce(&submit->depend_tx); for (i = 0; i < disks; i++) if (blocks[i] == NULL)
ptrs[i] = raid6_get_zero_page(); else
ptrs[i] = page_address(blocks[i]) + offs[i];
raid6_datap_recov(disks, bytes, faila, ptrs);
async_tx_sync_epilog(submit);
return NULL;
}
good_srcs = 0;
good = -1; for (i = 0; i < disks-2; i++) { if (i == faila) continue; if (blocks[i]) {
good = i;
good_srcs++; if (good_srcs > 1) break;
}
}
BUG_ON(good_srcs == 0);
/* Compute syndrome with zero for the missing data page *Usethedeaddatapageastemporarystoragefordeltaq
*/
dq = blocks[faila];
dq_off = offs[faila];
blocks[faila] = NULL;
blocks[disks-1] = dq;
offs[disks-1] = dq_off;
/* in the 4-disk case we only need to perform a single source *multiplicationwiththeonegooddatablock.
*/ if (good_srcs == 1) { struct page *g = blocks[good]; unsignedint g_off = offs[good];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.