aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crc-t10dif.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2013-09-12 15:31:34 +1000
committerHerbert Xu <herbert@gondor.apana.org.au>2013-09-12 15:31:34 +1000
commit26052f9b9bb8de4f6a57165b0a803de9c26138bd (patch)
tree4a22e3a8ae9dde1f1cc14eaad48eae8ad542f86a /lib/crc-t10dif.c
parent77dbd7a95e4a4f15264c333a9e9ab97ee27dc2aa (diff)
downloadkernel_goldelico_gta04-26052f9b9bb8de4f6a57165b0a803de9c26138bd.zip
kernel_goldelico_gta04-26052f9b9bb8de4f6a57165b0a803de9c26138bd.tar.gz
kernel_goldelico_gta04-26052f9b9bb8de4f6a57165b0a803de9c26138bd.tar.bz2
crypto: crct10dif - Add fallback for broken initrds
Unfortunately, even with a softdep some distros fail to include the necessary modules in the initrd. Therefore this patch adds a fallback path to restore existing behaviour where we cannot load the new crypto crct10dif algorithm. In order to do this, the underlying crct10dif has been split out from the crypto implementation so that it can be used on the fallback path. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib/crc-t10dif.c')
-rw-r--r--lib/crc-t10dif.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/lib/crc-t10dif.c b/lib/crc-t10dif.c
index 43bc5b0..dfe6ec1 100644
--- a/lib/crc-t10dif.c
+++ b/lib/crc-t10dif.c
@@ -14,8 +14,10 @@
#include <linux/err.h>
#include <linux/init.h>
#include <crypto/hash.h>
+#include <linux/static_key.h>
static struct crypto_shash *crct10dif_tfm;
+static struct static_key crct10dif_fallback __read_mostly;
__u16 crc_t10dif(const unsigned char *buffer, size_t len)
{
@@ -25,6 +27,9 @@ __u16 crc_t10dif(const unsigned char *buffer, size_t len)
} desc;
int err;
+ if (static_key_false(&crct10dif_fallback))
+ return crc_t10dif_generic(0, buffer, len);
+
desc.shash.tfm = crct10dif_tfm;
desc.shash.flags = 0;
*(__u16 *)desc.ctx = 0;
@@ -39,7 +44,11 @@ EXPORT_SYMBOL(crc_t10dif);
static int __init crc_t10dif_mod_init(void)
{
crct10dif_tfm = crypto_alloc_shash("crct10dif", 0, 0);
- return PTR_RET(crct10dif_tfm);
+ if (IS_ERR(crct10dif_tfm)) {
+ static_key_slow_inc(&crct10dif_fallback);
+ crct10dif_tfm = NULL;
+ }
+ return 0;
}
static void __exit crc_t10dif_mod_fini(void)