2011-12-07 18:59:47

by Seth Jennings

[permalink] [raw]
Subject: [PATCH 0/3] crypto: Add per-cpu transform helpers

This patchset includes two new functions for the cryptographic library,
crypto_alloc_percpu_tfms() and crypto_free_percpu_tfms(), which assist users
in allocating and freeing per-cpu transforms.

It also includes typing wrappers for the compression algorithm class.

The reason for this patch is that during my work to enable page compression
via the cryptographic API in the zcache staging driver, and realized that I
had rewritten some per-cpu transform code that already exists in the
xfrm_ipcomp code.

In an effort to avoid duplication, this patchset moves the per-cpu code into
helper functions in the cryptographic library and makes the necessary
modifications to the xfrm_ipcomp code.

After this change is (hopefully) merged, I will submit the zcache driver
changes, which will be the second user of these helpers.

Seth Jennings (3):
crypto: Add per-cpu transform alloc() and free()
crypto: Add inline per-cpu wrappers for compression
xfrm: Modify xfrm_ipcomp code to use new per-cpu helpers

crypto/api.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/crypto.h | 28 +++++++++++++++++++++
net/xfrm/xfrm_ipcomp.c | 34 ++++++--------------------
3 files changed, 98 insertions(+), 26 deletions(-)

--
1.7.5.4


2011-12-07 18:59:48

by Seth Jennings

[permalink] [raw]
Subject: [PATCH 1/3] crypto: Add per-cpu transform alloc() and free()

This patch add two functions for allocating a freeing
dynamically allocated per-cpu transform structures.

Signed-off-by: Seth Jennings <[email protected]>
---
crypto/api.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/crypto/api.c b/crypto/api.c
index 033a714..f95b3f9 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -602,5 +602,67 @@ int crypto_has_alg(const char *name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_has_alg);

+/*
+ * Per-cpu crypto helpers
+ *
+ * crypto_alloc_percpu_tfms() and crypto_free_percpu_tfms() are used for
+ * allocating tfms on a per-cpu basis. The set of cpus the tfms are
+ * allocated/freed on is determined by the cpumask (see linux/cpumask.h).
+ * If the cpu_possible_mask is used, then the user has a tfm for every cpu
+ * that could ever possibly enabled. However, if the user calls with cpumask
+ * cpu_online_mask or cpu_present_mask with HOTPLUG enabled, the user
+ * must register a cpu notifier to allocate/free the tfm for dynamically
+ * added/removed cpus.
+*/
+void crypto_free_percpu_tfms(struct crypto_tfm * __percpu *tfms,
+ const struct cpumask *cpumask)
+{
+ int cpu;
+ struct crypto_tfm *tfm;
+
+ if (!tfms)
+ return;
+
+ for_each_cpu(cpu, cpumask) {
+ tfm = *per_cpu_ptr(tfms, cpu);
+ if (!tfm)
+ continue;
+ crypto_free_tfm(tfm);
+ *per_cpu_ptr(tfms, cpu) = NULL;
+ }
+
+ free_percpu(tfms);
+}
+EXPORT_SYMBOL_GPL(crypto_free_percpu_tfms);
+
+struct crypto_tfm * __percpu *crypto_alloc_percpu_tfms(const char *alg_name,
+ u32 type, u32 mask, const struct cpumask *cpumask)
+{
+ int cpu, err;
+ struct crypto_tfm * __percpu *tfms, *tfm;
+
+ tfms = alloc_percpu(struct crypto_tfm *);
+ if (!tfms) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ for_each_cpu(cpu, cpumask) {
+ tfm = crypto_alloc_base(alg_name, type, mask);
+ if (IS_ERR(tfm)) {
+ err = PTR_ERR(tfm);
+ goto error;
+ }
+ *per_cpu_ptr(tfms, cpu) = tfm;
+ }
+ return tfms;
+
+error:
+ if (tfms)
+ crypto_free_percpu_tfms(tfms, cpumask);
+ return (struct crypto_tfm * __percpu *)(ERR_PTR(err));
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_percpu_tfms);
+
MODULE_DESCRIPTION("Cryptographic core API");
MODULE_LICENSE("GPL");
--
1.7.5.4

2011-12-07 18:59:10

by Seth Jennings

[permalink] [raw]
Subject: [PATCH 3/3] xfrm: Modify xfrm_ipcomp code to use new per-cpu helpers

This patch exchanges the per-cpu transform allocation/free
code in xfrm_ipcomp for a call to the new helper in the
cryptographic API

Signed-off-by: Seth Jennings <[email protected]>
---
net/xfrm/xfrm_ipcomp.c | 34 ++++++++--------------------------
1 files changed, 8 insertions(+), 26 deletions(-)

diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index e5246fb..d681fbd 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -245,7 +245,6 @@ static void * __percpu *ipcomp_alloc_scratches(void)
static void ipcomp_free_tfms(struct crypto_comp * __percpu *tfms)
{
struct ipcomp_tfms *pos;
- int cpu;

list_for_each_entry(pos, &ipcomp_tfms_list, list) {
if (pos->tfms == tfms)
@@ -259,15 +258,7 @@ static void ipcomp_free_tfms(struct crypto_comp * __percpu *tfms)

list_del(&pos->list);
kfree(pos);
-
- if (!tfms)
- return;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
- crypto_free_comp(tfm);
- }
- free_percpu(tfms);
+ crypto_free_percpu_comp(tfms, cpu_possible_mask);
}

static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
@@ -295,27 +286,18 @@ static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
if (!pos)
return NULL;

+ tfms = crypto_alloc_percpu_comp(alg_name, 0, CRYPTO_ALG_ASYNC,
+ cpu_possible_mask);
+ if (IS_ERR_VALUE((unsigned long)tfms)) {
+ kfree(pos);
+ return NULL;
+ }
+
pos->users = 1;
INIT_LIST_HEAD(&pos->list);
list_add(&pos->list, &ipcomp_tfms_list);

- pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
- if (!tfms)
- goto error;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- goto error;
- *per_cpu_ptr(tfms, cpu) = tfm;
- }
-
return tfms;
-
-error:
- ipcomp_free_tfms(tfms);
- return NULL;
}

static void ipcomp_free_data(struct ipcomp_data *ipcd)
--
1.7.5.4

2011-12-07 19:00:38

by Seth Jennings

[permalink] [raw]
Subject: [PATCH 2/3] crypto: Add inline per-cpu wrappers for compression

This patch adds wrapper functions for compression users
that allocate and free per-cpu compression transforms

Signed-off-by: Seth Jennings <[email protected]>
---
include/linux/crypto.h | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 8a94217..5ed19c1 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -483,6 +483,10 @@ struct crypto_attr_u32 {

struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask);
void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm);
+struct crypto_tfm * __percpu *crypto_alloc_percpu_tfms(const char *alg_name,
+ u32 type, u32 mask, const struct cpumask *cpumask);
+void crypto_free_percpu_tfms(struct crypto_tfm * __percpu *tfms,
+ const struct cpumask *cpumask);

static inline void crypto_free_tfm(struct crypto_tfm *tfm)
{
@@ -1213,6 +1217,12 @@ static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm)
return (struct crypto_comp *)tfm;
}

+static inline struct crypto_comp * __percpu *__crypto_comp_percpu_cast(
+ struct crypto_tfm * __percpu *tfms)
+{
+ return (struct crypto_comp * __percpu *)tfms;
+}
+
static inline struct crypto_comp *crypto_comp_cast(struct crypto_tfm *tfm)
{
BUG_ON((crypto_tfm_alg_type(tfm) ^ CRYPTO_ALG_TYPE_COMPRESS) &
@@ -1230,6 +1240,17 @@ static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name,
return __crypto_comp_cast(crypto_alloc_base(alg_name, type, mask));
}

+static inline struct crypto_comp * __percpu *crypto_alloc_percpu_comp(
+ const char *alg_name, u32 type, u32 mask, const struct cpumask *cpumask)
+{
+ type &= ~CRYPTO_ALG_TYPE_MASK;
+ type |= CRYPTO_ALG_TYPE_COMPRESS;
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ return __crypto_comp_percpu_cast(crypto_alloc_percpu_tfms(alg_name,
+ type, mask, cpumask));
+}
+
static inline struct crypto_tfm *crypto_comp_tfm(struct crypto_comp *tfm)
{
return &tfm->base;
@@ -1240,6 +1261,13 @@ static inline void crypto_free_comp(struct crypto_comp *tfm)
crypto_free_tfm(crypto_comp_tfm(tfm));
}

+static inline void crypto_free_percpu_comp(struct crypto_comp * __percpu *tfms,
+ const struct cpumask *cpumask)
+{
+ crypto_free_percpu_tfms((struct crypto_tfm * __percpu *)(tfms),
+ cpumask);
+}
+
static inline int crypto_has_comp(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
--
1.7.5.4