4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010 Oracle and/or its affiliates.
24 * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
28 * This file gets included by c files for implementing the full set
29 * of zfs_impl.h defines.
31 * It's ment for easier maintaining multiple implementations of
32 * algorithms. Look into blake3_impl.c, sha256_impl.c or sha512_impl.c
36 #include <sys/zfs_context.h>
37 #include <sys/zio_checksum.h>
38 #include <sys/zfs_impl.h>
40 /* Two default implementations */
41 #define IMPL_FASTEST (UINT32_MAX)
42 #define IMPL_CYCLE (UINT32_MAX - 1)
44 #define IMPL_READ(i) (*(volatile uint32_t *) &(i))
46 /* Implementation that contains the fastest method */
47 static IMPL_OPS_T generic_fastest_impl
= {
51 /* Hold all supported implementations */
52 static const IMPL_OPS_T
*generic_supp_impls
[ARRAY_SIZE(IMPL_ARRAY
)];
53 static uint32_t generic_supp_impls_cnt
= 0;
55 /* Currently selected implementation */
56 static uint32_t generic_impl_chosen
= IMPL_FASTEST
;
58 static struct generic_impl_selector
{
61 } generic_impl_selectors
[] = {
62 { "cycle", IMPL_CYCLE
},
63 { "fastest", IMPL_FASTEST
}
66 /* check the supported implementations */
68 generic_impl_init(void)
73 if (likely(generic_supp_impls_cnt
!= 0))
76 /* Move supported implementations into generic_supp_impls */
77 for (i
= 0, c
= 0; i
< ARRAY_SIZE(IMPL_ARRAY
); i
++) {
78 const IMPL_OPS_T
*impl
= IMPL_ARRAY
[i
];
80 if (impl
->is_supported
&& impl
->is_supported())
81 generic_supp_impls
[c
++] = impl
;
83 generic_supp_impls_cnt
= c
;
85 /* first init generic impl, may be changed via set_fastest() */
86 memcpy(&generic_fastest_impl
, generic_supp_impls
[0],
87 sizeof (generic_fastest_impl
));
90 /* get number of supported implementations */
92 generic_impl_getcnt(void)
95 return (generic_supp_impls_cnt
);
98 /* get id of selected implementation */
100 generic_impl_getid(void)
103 return (IMPL_READ(generic_impl_chosen
));
106 /* get name of selected implementation */
108 generic_impl_getname(void)
110 uint32_t impl
= IMPL_READ(generic_impl_chosen
);
119 return (generic_supp_impls
[impl
]->name
);
123 /* set implementation by id */
125 generic_impl_setid(uint32_t id
)
130 atomic_swap_32(&generic_impl_chosen
, IMPL_FASTEST
);
133 atomic_swap_32(&generic_impl_chosen
, IMPL_CYCLE
);
136 ASSERT3U(id
, <, generic_supp_impls_cnt
);
137 atomic_swap_32(&generic_impl_chosen
, id
);
142 /* set implementation by name */
144 generic_impl_setname(const char *val
)
146 uint32_t impl
= IMPL_READ(generic_impl_chosen
);
148 int i
, err
= -EINVAL
;
151 val_len
= strlen(val
);
152 while ((val_len
> 0) && !!isspace(val
[val_len
-1])) /* trim '\n' */
155 /* check mandatory implementations */
156 for (i
= 0; i
< ARRAY_SIZE(generic_impl_selectors
); i
++) {
157 const char *name
= generic_impl_selectors
[i
].name
;
159 if (val_len
== strlen(name
) &&
160 strncmp(val
, name
, val_len
) == 0) {
161 impl
= generic_impl_selectors
[i
].sel
;
167 /* check all supported implementations */
169 for (i
= 0; i
< generic_supp_impls_cnt
; i
++) {
170 const char *name
= generic_supp_impls
[i
]->name
;
172 if (val_len
== strlen(name
) &&
173 strncmp(val
, name
, val_len
) == 0) {
182 atomic_swap_32(&generic_impl_chosen
, impl
);
188 /* setup id as fastest implementation */
190 generic_impl_set_fastest(uint32_t id
)
193 memcpy(&generic_fastest_impl
, generic_supp_impls
[id
],
194 sizeof (generic_fastest_impl
));
197 /* return impl iterating functions */
198 const zfs_impl_t ZFS_IMPL_OPS
= {
200 .getcnt
= generic_impl_getcnt
,
201 .getid
= generic_impl_getid
,
202 .getname
= generic_impl_getname
,
203 .set_fastest
= generic_impl_set_fastest
,
204 .setid
= generic_impl_setid
,
205 .setname
= generic_impl_setname
208 /* get impl ops_t of selected implementation */
212 const IMPL_OPS_T
*ops
= NULL
;
213 uint32_t idx
, impl
= IMPL_READ(generic_impl_chosen
);
214 static uint32_t cycle_count
= 0;
219 ops
= &generic_fastest_impl
;
222 idx
= (++cycle_count
) % generic_supp_impls_cnt
;
223 ops
= generic_supp_impls
[idx
];
226 ASSERT3U(impl
, <, generic_supp_impls_cnt
);
227 ops
= generic_supp_impls
[impl
];
231 ASSERT3P(ops
, !=, NULL
);