brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 179eec9 Raw
118 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * RAID-6 data recovery in dual failure mode based on the XC instruction.4 *5 * Copyright IBM Corp. 20166 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>7 */8 9#include <linux/export.h>10#include <linux/raid/pq.h>11 12static inline void xor_block(u8 *p1, u8 *p2)13{14	typedef struct { u8 _[256]; } addrtype;15 16	asm volatile(17		"	xc	0(256,%[p1]),0(%[p2])\n"18		: "+m" (*(addrtype *) p1) : "m" (*(addrtype *) p2),19		  [p1] "a" (p1), [p2] "a" (p2) : "cc");20}21 22/* Recover two failed data blocks. */23static void raid6_2data_recov_s390xc(int disks, size_t bytes, int faila,24		int failb, void **ptrs)25{26	u8 *p, *q, *dp, *dq;27	const u8 *pbmul;	/* P multiplier table for B data */28	const u8 *qmul;		/* Q multiplier table (for both) */29	int i;30 31	p = (u8 *)ptrs[disks-2];32	q = (u8 *)ptrs[disks-1];33 34	/* Compute syndrome with zero for the missing data pages35	   Use the dead data pages as temporary storage for36	   delta p and delta q */37	dp = (u8 *)ptrs[faila];38	ptrs[faila] = (void *)raid6_empty_zero_page;39	ptrs[disks-2] = dp;40	dq = (u8 *)ptrs[failb];41	ptrs[failb] = (void *)raid6_empty_zero_page;42	ptrs[disks-1] = dq;43 44	raid6_call.gen_syndrome(disks, bytes, ptrs);45 46	/* Restore pointer table */47	ptrs[faila]   = dp;48	ptrs[failb]   = dq;49	ptrs[disks-2] = p;50	ptrs[disks-1] = q;51 52	/* Now, pick the proper data tables */53	pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];54	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];55 56	/* Now do it... */57	while (bytes) {58		xor_block(dp, p);59		xor_block(dq, q);60		for (i = 0; i < 256; i++)61			dq[i] = pbmul[dp[i]] ^ qmul[dq[i]];62		xor_block(dp, dq);63		p += 256;64		q += 256;65		dp += 256;66		dq += 256;67		bytes -= 256;68	}69}70 71/* Recover failure of one data block plus the P block */72static void raid6_datap_recov_s390xc(int disks, size_t bytes, int faila,73		void **ptrs)74{75	u8 *p, *q, *dq;76	const u8 *qmul;		/* Q multiplier table */77	int i;78 79	p = (u8 *)ptrs[disks-2];80	q = (u8 *)ptrs[disks-1];81 82	/* Compute syndrome with zero for the missing data page83	   Use the dead data page as temporary storage for delta q */84	dq = (u8 *)ptrs[faila];85	ptrs[faila] = (void *)raid6_empty_zero_page;86	ptrs[disks-1] = dq;87 88	raid6_call.gen_syndrome(disks, bytes, ptrs);89 90	/* Restore pointer table */91	ptrs[faila]   = dq;92	ptrs[disks-1] = q;93 94	/* Now, pick the proper data tables */95	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];96 97	/* Now do it... */98	while (bytes) {99		xor_block(dq, q);100		for (i = 0; i < 256; i++)101			dq[i] = qmul[dq[i]];102		xor_block(p, dq);103		p += 256;104		q += 256;105		dq += 256;106		bytes -= 256;107	}108}109 110 111const struct raid6_recov_calls raid6_recov_s390xc = {112	.data2 = raid6_2data_recov_s390xc,113	.datap = raid6_datap_recov_s390xc,114	.valid = NULL,115	.name = "s390xc",116	.priority = 1,117};118