Skip to content

Commit

Permalink
lib/raid6: Add SSSE3 optimized recovery functions
Browse files Browse the repository at this point in the history
Add SSSE3 optimized recovery functions, as well as a system
for selecting the most appropriate recovery functions to use.

Originally-by: H. Peter Anvin <[email protected]>
Signed-off-by: Jim Kukunas <[email protected]>
Signed-off-by: NeilBrown <[email protected]>
  • Loading branch information
jtkukunas authored and neilbrown committed May 22, 2012
1 parent f674ef7 commit 048a8b8
Show file tree
Hide file tree
Showing 6 changed files with 425 additions and 7 deletions.
18 changes: 16 additions & 2 deletions include/linux/raid/pq.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,20 @@ extern const struct raid6_calls raid6_altivec2;
extern const struct raid6_calls raid6_altivec4;
extern const struct raid6_calls raid6_altivec8;

struct raid6_recov_calls {
void (*data2)(int, size_t, int, int, void **);
void (*datap)(int, size_t, int, void **);
int (*valid)(void);
const char *name;
int priority;
};

extern const struct raid6_recov_calls raid6_recov_intx1;
extern const struct raid6_recov_calls raid6_recov_ssse3;

/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
extern const struct raid6_recov_calls *const raid6_recov_algos[];
int raid6_select_algo(void);

/* Return values from chk_syndrome */
Expand All @@ -111,14 +123,16 @@ int raid6_select_algo(void);

/* Galois field tables */
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256] __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256] __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));

/* Recovery routines */
void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
extern void (*raid6_2data_recov)(int disks, size_t bytes, int faila, int failb,
void **ptrs);
void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs);
extern void (*raid6_datap_recov)(int disks, size_t bytes, int faila,
void **ptrs);
void raid6_dual_recov(int disks, size_t bytes, int faila, int failb,
void **ptrs);

Expand Down
2 changes: 1 addition & 1 deletion lib/raid6/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
obj-$(CONFIG_RAID6_PQ) += raid6_pq.o

raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \
raid6_pq-y += algos.o recov.o recov_ssse3.o tables.o int1.o int2.o int4.o \
int8.o int16.o int32.o altivec1.o altivec2.o altivec4.o \
altivec8.o mmx.o sse1.o sse2.o
hostprogs-y += mktables
Expand Down
37 changes: 37 additions & 0 deletions lib/raid6/algos.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ const struct raid6_calls * const raid6_algos[] = {
NULL
};

void (*raid6_2data_recov)(int, size_t, int, int, void **);
EXPORT_SYMBOL_GPL(raid6_2data_recov);

void (*raid6_datap_recov)(int, size_t, int, void **);
EXPORT_SYMBOL_GPL(raid6_datap_recov);

const struct raid6_recov_calls *const raid6_recov_algos[] = {
#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
&raid6_recov_ssse3,
#endif
&raid6_recov_intx1,
NULL
};

#ifdef __KERNEL__
#define RAID6_TIME_JIFFIES_LG2 4
#else
Expand All @@ -72,6 +86,26 @@ const struct raid6_calls * const raid6_algos[] = {
#define time_before(x, y) ((x) < (y))
#endif

static inline void raid6_choose_recov(void)
{
const struct raid6_recov_calls *const *algo;
const struct raid6_recov_calls *best;

for (best = NULL, algo = raid6_recov_algos; *algo; algo++)
if (!best || (*algo)->priority > best->priority)
if (!(*algo)->valid || (*algo)->valid())
best = *algo;

if (best) {
raid6_2data_recov = best->data2;
raid6_datap_recov = best->datap;

printk("raid6: using %s recovery algorithm\n", best->name);
} else
printk("raid6: Yikes! No recovery algorithm found!\n");
}


/* Try to pick the best algorithm */
/* This code uses the gfmul table as convenient data set to abuse */

Expand Down Expand Up @@ -141,6 +175,9 @@ int __init raid6_select_algo(void)

free_pages((unsigned long)syndromes, 1);

/* select raid recover functions */
raid6_choose_recov();

return best ? 0 : -EINVAL;
}

Expand Down
25 changes: 25 additions & 0 deletions lib/raid6/mktables.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,31 @@ int main(int argc, char *argv[])
printf("EXPORT_SYMBOL(raid6_gfmul);\n");
printf("#endif\n");

/* Compute vector multiplication table */
printf("\nconst u8 __attribute__((aligned(256)))\n"
"raid6_vgfmul[256][32] =\n"
"{\n");
for (i = 0; i < 256; i++) {
printf("\t{\n");
for (j = 0; j < 16; j += 8) {
printf("\t\t");
for (k = 0; k < 8; k++)
printf("0x%02x,%c", gfmul(i, j + k),
(k == 7) ? '\n' : ' ');
}
for (j = 0; j < 16; j += 8) {
printf("\t\t");
for (k = 0; k < 8; k++)
printf("0x%02x,%c", gfmul(i, (j + k) << 4),
(k == 7) ? '\n' : ' ');
}
printf("\t},\n");
}
printf("};\n");
printf("#ifdef __KERNEL__\n");
printf("EXPORT_SYMBOL(raid6_vgfmul);\n");
printf("#endif\n");

/* Compute power-of-2 table (exponent) */
v = 1;
printf("\nconst u8 __attribute__((aligned(256)))\n"
Expand Down
15 changes: 11 additions & 4 deletions lib/raid6/recov.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <linux/raid/pq.h>

/* Recover two failed data blocks. */
void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, int failb,
void **ptrs)
{
u8 *p, *q, *dp, *dq;
Expand Down Expand Up @@ -64,10 +64,9 @@ void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
p++; q++;
}
}
EXPORT_SYMBOL_GPL(raid6_2data_recov);

/* Recover failure of one data block plus the P block */
void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
void raid6_datap_recov_intx1(int disks, size_t bytes, int faila, void **ptrs)
{
u8 *p, *q, *dq;
const u8 *qmul; /* Q multiplier table */
Expand Down Expand Up @@ -96,7 +95,15 @@ void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
q++; dq++;
}
}
EXPORT_SYMBOL_GPL(raid6_datap_recov);


const struct raid6_recov_calls raid6_recov_intx1 = {
.data2 = raid6_2data_recov_intx1,
.datap = raid6_datap_recov_intx1,
.valid = NULL,
.name = "intx1",
.priority = 0,
};

#ifndef __KERNEL__
/* Testing only */
Expand Down
Loading

0 comments on commit 048a8b8

Please sign in to comment.