From: Seth Jennings <sjenning@linux.vnet.ibm.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Seth Jennings <sjenning@linux.vnet.ibm.com>,
Dan Magenheimer <dan.magenheimer@oracle.com>,
Nitin Gupta <ngupta@vflare.org>,
Dave Hansen <dave@linux.vnet.ibm.com>,
devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org,
Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>,
Brian King <brking@linux.vnet.ibm.com>,
Robert Jennings <rcj@linux.vnet.ibm.com>
Subject: Re: [PATCHv2] staging: zcache: crypto API support
Date: Mon, 06 Feb 2012 15:25:21 -0600 [thread overview]
Message-ID: <4F304541.8000602@linux.vnet.ibm.com> (raw)
In-Reply-To: <1325629894-10967-1-git-send-email-sjenning@linux.vnet.ibm.com>
Also this one:
https://lkml.org/lkml/2012/1/3/263
Bigger change, might be a merge-window sized commit.
Also Acked by Dan:
https://lkml.org/lkml/2012/1/4/240
Thanks
--
Seth
On 01/03/2012 04:31 PM, Seth Jennings wrote:
> This patch allow zcache to use the crypto API for page compression.
> It replaces the direct LZO compress/decompress calls with calls
> into the crypto compression API. The compressor to be used is
> specified in the kernel boot line with the zcache parameter like:
> zcache=lzo or zcache=deflate. If the specified compressor can't
> be loaded, zcache uses lzo as the default compressor.
>
> Signed-off-by: Seth Jennings <sjenning@linux.vnet.ibm.com>
> ---
> drivers/staging/zcache/Kconfig | 7 +-
> drivers/staging/zcache/zcache-main.c | 150 ++++++++++++++++++++++++++++------
> 2 files changed, 126 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig
> index 7fabcb2..1b7bba7 100644
> --- a/drivers/staging/zcache/Kconfig
> +++ b/drivers/staging/zcache/Kconfig
> @@ -1,13 +1,12 @@
> config ZCACHE
> tristate "Dynamic compression of swap pages and clean pagecache pages"
> - depends on CLEANCACHE || FRONTSWAP
> + depends on (CLEANCACHE || FRONTSWAP) && CRYPTO
> select XVMALLOC
> - select LZO_COMPRESS
> - select LZO_DECOMPRESS
> + select CRYPTO_LZO
> default n
> help
> Zcache doubles RAM efficiency while providing a significant
> - performance boosts on many workloads. Zcache uses lzo1x
> + performance boosts on many workloads. Zcache uses
> compression and an in-kernel implementation of transcendent
> memory to store clean page cache pages and swap in RAM,
> providing a noticeable reduction in disk I/O.
> diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
> index 56c1f9c..a4384eb 100644
> --- a/drivers/staging/zcache/zcache-main.c
> +++ b/drivers/staging/zcache/zcache-main.c
> @@ -6,7 +6,8 @@
> *
> * Zcache provides an in-kernel "host implementation" for transcendent memory
> * and, thus indirectly, for cleancache and frontswap. Zcache includes two
> - * page-accessible memory [1] interfaces, both utilizing lzo1x compression:
> + * page-accessible memory [1] interfaces, both utilizing the crypto compression
> + * API:
> * 1) "compression buddies" ("zbud") is used for ephemeral pages
> * 2) xvmalloc is used for persistent pages.
> * Xvmalloc (based on the TLSF allocator) has very low fragmentation
> @@ -23,12 +24,13 @@
> #include <linux/cpu.h>
> #include <linux/highmem.h>
> #include <linux/list.h>
> -#include <linux/lzo.h>
> #include <linux/slab.h>
> #include <linux/spinlock.h>
> #include <linux/types.h>
> #include <linux/atomic.h>
> #include <linux/math64.h>
> +#include <linux/crypto.h>
> +#include <linux/string.h>
> #include "tmem.h"
>
> #include "../zram/xvmalloc.h" /* if built in drivers/staging */
> @@ -81,6 +83,38 @@ static inline bool is_local_client(struct zcache_client *cli)
> return cli == &zcache_host;
> }
>
> +/* crypto API for zcache */
> +#define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME
> +static char zcache_comp_name[ZCACHE_COMP_NAME_SZ];
> +static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms;
> +
> +enum comp_op {
> + ZCACHE_COMPOP_COMPRESS,
> + ZCACHE_COMPOP_DECOMPRESS
> +};
> +
> +static inline int zcache_comp_op(enum comp_op op,
> + const u8 *src, unsigned int slen,
> + u8 *dst, unsigned int *dlen)
> +{
> + struct crypto_comp *tfm;
> + int ret;
> +
> + BUG_ON(!zcache_comp_pcpu_tfms);
> + tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, get_cpu());
> + BUG_ON(!tfm);
> + switch (op) {
> + case ZCACHE_COMPOP_COMPRESS:
> + ret = crypto_comp_compress(tfm, src, slen, dst, dlen);
> + break;
> + case ZCACHE_COMPOP_DECOMPRESS:
> + ret = crypto_comp_decompress(tfm, src, slen, dst, dlen);
> + break;
> + }
> + put_cpu();
> + return ret;
> +}
> +
> /**********
> * Compression buddies ("zbud") provides for packing two (or, possibly
> * in the future, more) compressed ephemeral pages into a single "raw"
> @@ -408,7 +442,7 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
> {
> struct zbud_page *zbpg;
> unsigned budnum = zbud_budnum(zh);
> - size_t out_len = PAGE_SIZE;
> + unsigned int out_len = PAGE_SIZE;
> char *to_va, *from_va;
> unsigned size;
> int ret = 0;
> @@ -425,8 +459,9 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
> to_va = kmap_atomic(page, KM_USER0);
> size = zh->size;
> from_va = zbud_data(zh, size);
> - ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len);
> - BUG_ON(ret != LZO_E_OK);
> + ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, from_va, size,
> + to_va, &out_len);
> + BUG_ON(ret);
> BUG_ON(out_len != PAGE_SIZE);
> kunmap_atomic(to_va, KM_USER0);
> out:
> @@ -624,7 +659,7 @@ static int zbud_show_cumul_chunk_counts(char *buf)
>
> /**********
> * This "zv" PAM implementation combines the TLSF-based xvMalloc
> - * with lzo1x compression to maximize the amount of data that can
> + * with the crypto compression API to maximize the amount of data that can
> * be packed into a physical page.
> *
> * Zv represents a PAM page with the index and object (plus a "size" value
> @@ -711,7 +746,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
>
> static void zv_decompress(struct page *page, struct zv_hdr *zv)
> {
> - size_t clen = PAGE_SIZE;
> + unsigned int clen = PAGE_SIZE;
> char *to_va;
> unsigned size;
> int ret;
> @@ -720,10 +755,10 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv)
> size = xv_get_object_size(zv) - sizeof(*zv);
> BUG_ON(size == 0);
> to_va = kmap_atomic(page, KM_USER0);
> - ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv),
> - size, to_va, &clen);
> + ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, (char *)zv + sizeof(*zv),
> + size, to_va, &clen);
> kunmap_atomic(to_va, KM_USER0);
> - BUG_ON(ret != LZO_E_OK);
> + BUG_ON(ret);
> BUG_ON(clen != PAGE_SIZE);
> }
>
> @@ -1286,25 +1321,24 @@ static struct tmem_pamops zcache_pamops = {
> * zcache compression/decompression and related per-cpu stuff
> */
>
> -#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS
> -#define LZO_DSTMEM_PAGE_ORDER 1
> -static DEFINE_PER_CPU(unsigned char *, zcache_workmem);
> static DEFINE_PER_CPU(unsigned char *, zcache_dstmem);
> +#define ZCACHE_DSTMEM_ORDER 1
>
> static int zcache_compress(struct page *from, void **out_va, size_t *out_len)
> {
> int ret = 0;
> unsigned char *dmem = __get_cpu_var(zcache_dstmem);
> - unsigned char *wmem = __get_cpu_var(zcache_workmem);
> char *from_va;
>
> BUG_ON(!irqs_disabled());
> - if (unlikely(dmem == NULL || wmem == NULL))
> - goto out; /* no buffer, so can't compress */
> + if (unlikely(dmem == NULL))
> + goto out; /* no buffer or no compressor so can't compress */
> + *out_len = PAGE_SIZE << ZCACHE_DSTMEM_ORDER;
> from_va = kmap_atomic(from, KM_USER0);
> mb();
> - ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem);
> - BUG_ON(ret != LZO_E_OK);
> + ret = zcache_comp_op(ZCACHE_COMPOP_COMPRESS, from_va, PAGE_SIZE, dmem,
> + (unsigned int *)out_len);
> + BUG_ON(ret);
> *out_va = dmem;
> kunmap_atomic(from_va, KM_USER0);
> ret = 1;
> @@ -1312,29 +1346,48 @@ out:
> return ret;
> }
>
> +static int zcache_comp_cpu_up(int cpu)
> +{
> + struct crypto_comp *tfm;
> +
> + tfm = crypto_alloc_comp(zcache_comp_name, 0, 0);
> + if (IS_ERR(tfm))
> + return NOTIFY_BAD;
> + *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = tfm;
> + return NOTIFY_OK;
> +}
> +
> +static void zcache_comp_cpu_down(int cpu)
> +{
> + struct crypto_comp *tfm;
> +
> + tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu);
> + crypto_free_comp(tfm);
> + *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = NULL;
> +}
>
> static int zcache_cpu_notifier(struct notifier_block *nb,
> unsigned long action, void *pcpu)
> {
> - int cpu = (long)pcpu;
> + int ret, cpu = (long)pcpu;
> struct zcache_preload *kp;
>
> switch (action) {
> case CPU_UP_PREPARE:
> + ret = zcache_comp_cpu_up(cpu);
> + if (ret != NOTIFY_OK) {
> + pr_err("zcache: can't allocate compressor transform\n");
> + return ret;
> + }
> per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages(
> - GFP_KERNEL | __GFP_REPEAT,
> - LZO_DSTMEM_PAGE_ORDER),
> - per_cpu(zcache_workmem, cpu) =
> - kzalloc(LZO1X_MEM_COMPRESS,
> - GFP_KERNEL | __GFP_REPEAT);
> + GFP_KERNEL | __GFP_REPEAT, ZCACHE_DSTMEM_ORDER);
> break;
> case CPU_DEAD:
> case CPU_UP_CANCELED:
> + zcache_comp_cpu_down(cpu);
> free_pages((unsigned long)per_cpu(zcache_dstmem, cpu),
> - LZO_DSTMEM_PAGE_ORDER);
> + ZCACHE_DSTMEM_ORDER);
> per_cpu(zcache_dstmem, cpu) = NULL;
> - kfree(per_cpu(zcache_workmem, cpu));
> - per_cpu(zcache_workmem, cpu) = NULL;
> kp = &per_cpu(zcache_preloads, cpu);
> while (kp->nr) {
> kmem_cache_free(zcache_objnode_cache,
> @@ -1919,6 +1972,44 @@ static int __init no_frontswap(char *s)
>
> __setup("nofrontswap", no_frontswap);
>
> +static int __init enable_zcache_compressor(char *s)
> +{
> + strncpy(zcache_comp_name, s, ZCACHE_COMP_NAME_SZ);
> + zcache_enabled = 1;
> + return 1;
> +}
> +__setup("zcache=", enable_zcache_compressor);
> +
> +
> +static int zcache_comp_init(void)
> +{
> + int ret = 0;
> +
> + /* check crypto algorithm */
> + if (*zcache_comp_name != '\0') {
> + ret = crypto_has_comp(zcache_comp_name, 0, 0);
> + if (!ret)
> + pr_info("zcache: %s not supported\n",
> + zcache_comp_name);
> + }
> + if (!ret)
> + strcpy(zcache_comp_name, "lzo");
> + ret = crypto_has_comp(zcache_comp_name, 0, 0);
> + if (!ret) {
> + ret = 1;
> + goto out;
> + }
> + pr_info("zcache: using %s compressor\n", zcache_comp_name);
> +
> + /* alloc percpu transforms */
> + ret = 0;
> + zcache_comp_pcpu_tfms = alloc_percpu(struct crypto_comp *);
> + if (!zcache_comp_pcpu_tfms)
> + ret = 1;
> +out:
> + return ret;
> +}
> +
> static int __init zcache_init(void)
> {
> int ret = 0;
> @@ -1941,6 +2032,11 @@ static int __init zcache_init(void)
> pr_err("zcache: can't register cpu notifier\n");
> goto out;
> }
> + ret = zcache_comp_init();
> + if (ret) {
> + pr_err("zcache: compressor initialization failed\n");
> + goto out;
> + }
> for_each_online_cpu(cpu) {
> void *pcpu = (void *)(long)cpu;
> zcache_cpu_notifier(&zcache_cpu_notifier_block,
next prev parent reply other threads:[~2012-02-06 21:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-03 22:31 [PATCHv2] staging: zcache: crypto API support Seth Jennings
2012-02-06 21:25 ` Seth Jennings [this message]
[not found] <<1325629894-10967-1-git-send-email-sjenning@linux.vnet.ibm.com>
2012-01-04 18:43 ` Dan Magenheimer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F304541.8000602@linux.vnet.ibm.com \
--to=sjenning@linux.vnet.ibm.com \
--cc=brking@linux.vnet.ibm.com \
--cc=cascardo@holoscopio.com \
--cc=dan.magenheimer@oracle.com \
--cc=dave@linux.vnet.ibm.com \
--cc=devel@driverdev.osuosl.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ngupta@vflare.org \
--cc=rcj@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.