Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
92203b0
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
ipc
kernel
lib
842
crypto
dim
fonts
kunit
livepatch
lz4
lzo
math
mpi
raid6
test
.gitignore
Makefile
algos.c
altivec.uc
avx2.c
avx512.c
int.uc
mktables.c
mmx.c
neon.c
neon.uc
recov.c
recov_avx2.c
recov_avx512.c
recov_neon.c
recov_neon_inner.c
recov_s390xc.c
recov_ssse3.c
s390vx.uc
sse1.c
sse2.c
unroll.awk
vpermxor.uc
x86.h
reed_solomon
vdso
xz
zlib_deflate
zlib_dfltcc
zlib_inflate
zstd
.gitignore
Kconfig
Kconfig.debug
Kconfig.kasan
Kconfig.kgdb
Kconfig.ubsan
Makefile
argv_split.c
ashldi3.c
ashrdi3.c
asn1_decoder.c
assoc_array.c
atomic64.c
atomic64_test.c
audit.c
bcd.c
bch.c
bitmap.c
bitrev.c
bootconfig.c
bsearch.c
btree.c
bucket_locks.c
bug.c
build_OID_registry
bust_spinlocks.c
check_signature.c
checksum.c
clz_ctz.c
clz_tab.c
cmdline.c
cmpdi2.c
compat_audit.c
cpu_rmap.c
cpumask.c
crc-ccitt.c
crc-itu-t.c
crc-t10dif.c
crc16.c
crc32.c
crc32defs.h
crc32test.c
crc4.c
crc64.c
crc7.c
crc8.c
ctype.c
debug_info.c
debug_locks.c
debugobjects.c
dec_and_lock.c
decompress.c
decompress_bunzip2.c
decompress_inflate.c
decompress_unlz4.c
decompress_unlzma.c
decompress_unlzo.c
decompress_unxz.c
devres.c
digsig.c
dump_stack.c
dynamic_debug.c
dynamic_queue_limits.c
earlycpio.c
errname.c
error-inject.c
errseq.c
extable.c
fault-inject.c
fdt.c
fdt_addresses.c
fdt_empty_tree.c
fdt_ro.c
fdt_rw.c
fdt_strerror.c
fdt_sw.c
fdt_wip.c
find_bit.c
find_bit_benchmark.c
flex_proportions.c
gen_crc32table.c
gen_crc64table.c
genalloc.c
generic-radix-tree.c
glob.c
globtest.c
hexdump.c
hweight.c
idr.c
inflate.c
interval_tree.c
interval_tree_test.c
iomap.c
iomap_copy.c
iommu-helper.c
ioremap.c
iov_iter.c
irq_poll.c
irq_regs.c
is_single_threaded.c
kasprintf.c
kfifo.c
klist.c
kobject.c
kobject_uevent.c
kstrtox.c
kstrtox.h
libcrc32c.c
list-test.c
list_debug.c
list_sort.c
llist.c
locking-selftest-hardirq.h
locking-selftest-mutex.h
locking-selftest-rlock-hardirq.h
locking-selftest-rlock-softirq.h
locking-selftest-rlock.h
locking-selftest-rsem.h
locking-selftest-rtmutex.h
locking-selftest-softirq.h
locking-selftest-spin-hardirq.h
locking-selftest-spin-softirq.h
locking-selftest-spin.h
locking-selftest-wlock-hardirq.h
locking-selftest-wlock-softirq.h
locking-selftest-wlock.h
locking-selftest-wsem.h
locking-selftest.c
lockref.c
logic_pio.c
lru_cache.c
lshrdi3.c
memcat_p.c
memory-notifier-error-inject.c
memregion.c
memweight.c
muldi3.c
net_utils.c
netdev-notifier-error-inject.c
nlattr.c
nmi_backtrace.c
nodemask.c
notifier-error-inject.c
notifier-error-inject.h
objagg.c
of-reconfig-notifier-error-inject.c
oid_registry.c
once.c
packing.c
parman.c
parser.c
pci_iomap.c
percpu-refcount.c
percpu_counter.c
percpu_test.c
plist.c
pm-notifier-error-inject.c
radix-tree.c
random32.c
ratelimit.c
rbtree.c
rbtree_test.c
refcount.c
rhashtable.c
sbitmap.c
scatterlist.c
seq_buf.c
sg_pool.c
sg_split.c
sha1.c
show_mem.c
siphash.c
smp_processor_id.c
sort.c
stackdepot.c
stmp_device.c
string.c
string_helpers.c
strncpy_from_user.c
strnlen_user.c
syscall.c
test-kstrtox.c
test-string_helpers.c
test_bitfield.c
test_bitmap.c
test_blackhole_dev.c
test_bpf.c
test_debug_virtual.c
test_firmware.c
test_hash.c
test_hexdump.c
test_ida.c
test_kasan.c
test_kmod.c
test_list_sort.c
test_lockup.c
test_memcat_p.c
test_meminit.c
test_min_heap.c
test_module.c
test_objagg.c
test_overflow.c
test_parman.c
test_printf.c
test_rhashtable.c
test_siphash.c
test_sort.c
test_stackinit.c
test_static_key_base.c
test_static_keys.c
test_string.c
test_strscpy.c
test_sysctl.c
test_ubsan.c
test_user_copy.c
test_uuid.c
test_vmalloc.c
test_xarray.c
textsearch.c
timerqueue.c
ts_bm.c
ts_fsm.c
ts_kmp.c
ubsan.c
ubsan.h
ucmpdi2.c
ucs2_string.c
usercopy.c
uuid.c
vsprintf.c
win_minmax.c
xarray.c
xxhash.c
mm
net
samples
scripts
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
lib
/
raid6
/
algos.c
Blame
Blame
Latest commit
History
History
289 lines (248 loc) · 6.53 KB
Breadcrumbs
linux
/
lib
/
raid6
/
algos.c
Top
File metadata and controls
Code
Blame
289 lines (248 loc) · 6.53 KB
Raw
// SPDX-License-Identifier: GPL-2.0-or-later /* -*- linux-c -*- ------------------------------------------------------- * * * Copyright 2002 H. Peter Anvin - All Rights Reserved * * ----------------------------------------------------------------------- */ /* * raid6/algos.c * * Algorithm list and algorithm selection for RAID-6 */ #include <linux/raid/pq.h> #ifndef __KERNEL__ #include <sys/mman.h> #include <stdio.h> #else #include <linux/module.h> #include <linux/gfp.h> #if !RAID6_USE_EMPTY_ZERO_PAGE /* In .bss so it's zeroed */ const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); EXPORT_SYMBOL(raid6_empty_zero_page); #endif #endif struct raid6_calls raid6_call; EXPORT_SYMBOL_GPL(raid6_call); const struct raid6_calls * const raid6_algos[] = { #if defined(__i386__) && !defined(__arch_um__) #ifdef CONFIG_AS_AVX512 &raid6_avx512x2, &raid6_avx512x1, #endif #ifdef CONFIG_AS_AVX2 &raid6_avx2x2, &raid6_avx2x1, #endif &raid6_sse2x2, &raid6_sse2x1, &raid6_sse1x2, &raid6_sse1x1, &raid6_mmxx2, &raid6_mmxx1, #endif #if defined(__x86_64__) && !defined(__arch_um__) #ifdef CONFIG_AS_AVX512 &raid6_avx512x4, &raid6_avx512x2, &raid6_avx512x1, #endif #ifdef CONFIG_AS_AVX2 &raid6_avx2x4, &raid6_avx2x2, &raid6_avx2x1, #endif &raid6_sse2x4, &raid6_sse2x2, &raid6_sse2x1, #endif #ifdef CONFIG_ALTIVEC &raid6_vpermxor8, &raid6_vpermxor4, &raid6_vpermxor2, &raid6_vpermxor1, &raid6_altivec8, &raid6_altivec4, &raid6_altivec2, &raid6_altivec1, #endif #if defined(CONFIG_S390) &raid6_s390vx8, #endif #ifdef CONFIG_KERNEL_MODE_NEON &raid6_neonx8, &raid6_neonx4, &raid6_neonx2, &raid6_neonx1, #endif #if defined(__ia64__) &raid6_intx32, &raid6_intx16, #endif &raid6_intx8, &raid6_intx4, &raid6_intx2, &raid6_intx1, 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[] = { #ifdef CONFIG_X86 #ifdef CONFIG_AS_AVX512 &raid6_recov_avx512, #endif #ifdef CONFIG_AS_AVX2 &raid6_recov_avx2, #endif &raid6_recov_ssse3, #endif #ifdef CONFIG_S390 &raid6_recov_s390xc, #endif #if defined(CONFIG_KERNEL_MODE_NEON) &raid6_recov_neon, #endif &raid6_recov_intx1, NULL }; #ifdef __KERNEL__ #define RAID6_TIME_JIFFIES_LG2 4 #else /* Need more time to be stable in userspace */ #define RAID6_TIME_JIFFIES_LG2 9 #define time_before(x, y) ((x) < (y)) #endif #define RAID6_TEST_DISKS 8 #define RAID6_TEST_DISKS_ORDER 3 static inline const struct raid6_recov_calls *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; pr_info("raid6: using %s recovery algorithm\n", best->name); } else pr_err("raid6: Yikes! No recovery algorithm found!\n"); return best; } static inline const struct raid6_calls *raid6_choose_gen( void *(*const dptrs)[RAID6_TEST_DISKS], const int disks) { unsigned long perf, bestgenperf, bestxorperf, j0, j1; int start = (disks>>1)-1, stop = disks-3; /* work on the second half of the disks */ const struct raid6_calls *const *algo; const struct raid6_calls *best; for (bestgenperf = 0, bestxorperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) { if (!best || (*algo)->prefer >= best->prefer) { if ((*algo)->valid && !(*algo)->valid()) continue; if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) { best = *algo; break; } perf = 0; preempt_disable(); j0 = jiffies; while ((j1 = jiffies) == j0) cpu_relax(); while (time_before(jiffies, j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { (*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs); perf++; } preempt_enable(); if (perf > bestgenperf) { bestgenperf = perf; best = *algo; } pr_info("raid6: %-8s gen() %5ld MB/s\n", (*algo)->name, (perf * HZ * (disks-2)) >> (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2)); if (!(*algo)->xor_syndrome) continue; perf = 0; preempt_disable(); j0 = jiffies; while ((j1 = jiffies) == j0) cpu_relax(); while (time_before(jiffies, j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { (*algo)->xor_syndrome(disks, start, stop, PAGE_SIZE, *dptrs); perf++; } preempt_enable(); if (best == *algo) bestxorperf = perf; pr_info("raid6: %-8s xor() %5ld MB/s\n", (*algo)->name, (perf * HZ * (disks-2)) >> (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2 + 1)); } } if (best) { if (IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) { pr_info("raid6: using algorithm %s gen() %ld MB/s\n", best->name, (bestgenperf * HZ * (disks-2)) >> (20 - PAGE_SHIFT+RAID6_TIME_JIFFIES_LG2)); if (best->xor_syndrome) pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n", (bestxorperf * HZ * (disks-2)) >> (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2 + 1)); } else pr_info("raid6: skip pq benchmark and using algorithm %s\n", best->name); raid6_call = *best; } else pr_err("raid6: Yikes! No algorithm found!\n"); return best; } /* Try to pick the best algorithm */ /* This code uses the gfmul table as convenient data set to abuse */ int __init raid6_select_algo(void) { const int disks = RAID6_TEST_DISKS; const struct raid6_calls *gen_best; const struct raid6_recov_calls *rec_best; char *disk_ptr, *p; void *dptrs[RAID6_TEST_DISKS]; int i, cycle; /* prepare the buffer and fill it circularly with gfmul table */ disk_ptr = (char *)__get_free_pages(GFP_KERNEL, RAID6_TEST_DISKS_ORDER); if (!disk_ptr) { pr_err("raid6: Yikes! No memory available.\n"); return -ENOMEM; } p = disk_ptr; for (i = 0; i < disks; i++) dptrs[i] = p + PAGE_SIZE * i; cycle = ((disks - 2) * PAGE_SIZE) / 65536; for (i = 0; i < cycle; i++) { memcpy(p, raid6_gfmul, 65536); p += 65536; } if ((disks - 2) * PAGE_SIZE % 65536) memcpy(p, raid6_gfmul, (disks - 2) * PAGE_SIZE % 65536); /* select raid gen_syndrome function */ gen_best = raid6_choose_gen(&dptrs, disks); /* select raid recover functions */ rec_best = raid6_choose_recov(); free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER); return gen_best && rec_best ? 0 : -EINVAL; } static void raid6_exit(void) { do { } while (0); } subsys_initcall(raid6_select_algo); module_exit(raid6_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("RAID6 Q-syndrome calculations");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
You can’t perform that action at this time.