[PATCH] erofs: support external crypto for decompression

Gao Xiang hsiangkao at linux.alibaba.com
Thu Jun 6 18:10:49 AEST 2024


Hi,

On 2024/6/6 15:53, Tao Zeng via B4 Relay wrote:
> From: Tao Zeng <tao.zeng at amlogic.com>
> 
> Some SoCs have hardware decompressors which using private algorithms,
> which can be used for accelerating decompression for EROFS, but
> current EROFS decompressor architecture do not support external
> decompressors, this change adds a crypto layer interface for decompression
> and can be used to hook SoC vendor's decompressor by crypto name. Soc
> vendors can develop their own code which can be added to crypto layer.

There are several fundamental points with this stuff.

First, I think using crypto APIs to support hardware accelerators
_may_ be fine (I also plan to use crypto APIs for Intel IAA
accelerator), as long as you contribute your SoC accelerator
implementation upstream.

Using crypto APIs for out-of-tree external drivers as workaround
doesn't work on my side (or I guess the whole Linux project).

> 
> Signed-off-by: Tao Zeng <tao.zeng at amlogic.com>
> ---
>   fs/erofs/Kconfig                |  19 +++
>   fs/erofs/Makefile               |   1 +
>   fs/erofs/compress.h             |  28 ++++
>   fs/erofs/decompressor.c         |   7 +
>   fs/erofs/decompressor_cryptor.c | 306 ++++++++++++++++++++++++++++++++++++++++
>   fs/erofs/erofs_fs.h             |  14 ++
>   fs/erofs/internal.h             |   4 +
>   fs/erofs/super.c                |   8 +-
>   8 files changed, 386 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
> index 7dcdce660cac..72e29041244b 100644
> --- a/fs/erofs/Kconfig
> +++ b/fs/erofs/Kconfig
> @@ -127,6 +127,25 @@ config EROFS_FS_ZIP_ZSTD
>   
>   	  If unsure, say N.
>   
> +config EROFS_FS_ZIP_CRYPTO
> +	bool "EROFS external crypto decompress support"

	bool "EROFS crypto decompressor support"

> +	depends on EROFS_FS_ZIP
> +	help
> +	  Saying Y here to support external crypto for decompressing EROFS
> +	  file systems. Some SoCs have hardware decompressor with private
> +	  algorithm, which can be used for accelarating decompression of

	Sorry upstream Linux doesn't support private out-of-tree algorithms.

> +	  EROFS. This config enables external cryptos.

	help
	  Saying Y here to use specific crypto decompressors to decompress
	  EROFS file systems instead of software implementation, which can
	  be used for offloading asynchronous requests to accelerators.

	  If unsure, say N.

> +
> +	  If unsure, say N.
> +
> +config EROFS_CRYPTO_MAX_DISTANCE_PAGES
> +	int "EROFS max distance pages for crypto usage"
> +	default 32
> +	help
> +	  This config defines max distance pages for external crypto. Crypto
> +	  layer will use this value to grow up PCP buffers.
> +	  The default value is 128KB(32 pages).

No, I don't think it's of any use for accelerators.

> +
>   config EROFS_FS_ONDEMAND
>   	bool "EROFS fscache-based on-demand read support"
>   	depends on EROFS_FS
> diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile
> index 097d672e6b14..d2dc5e2d20bd 100644
> --- a/fs/erofs/Makefile
> +++ b/fs/erofs/Makefile
> @@ -7,4 +7,5 @@ erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o zutil.o
>   erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o
>   erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) += decompressor_deflate.o
>   erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) += decompressor_zstd.o
> +erofs-$(CONFIG_EROFS_FS_ZIP_CRYPTO) += decompressor_cryptor.o
>   erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o
> diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h
> index 19d53c30c8af..8236775563a5 100644
> --- a/fs/erofs/compress.h
> +++ b/fs/erofs/compress.h
> @@ -98,4 +98,32 @@ int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
>   			       struct page **pagepool);
>   int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
>   			    struct page **pgpl);
> +
> +#ifdef CONFIG_EROFS_FS_ZIP_CRYPTO
> +/* for external cryto decompress */
> +int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
> +			      struct page **pagepool);
> +int z_erofs_load_crypto_config(struct super_block *sb,
> +			       struct erofs_super_block *dsb,
> +			       void *data, int size);
> +#else
> +static inline int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
> +					    struct page **pagepool)
> +{
> +	return -EINVAL;
> +}
> +
> +static inline int z_erofs_load_crypto_config(struct super_block *sb,
> +					     struct erofs_super_block *dsb,
> +					     void *data,
> +					     int size);
> +{
> +	if (crypto) {
> +		erofs_err(sb, "crypto algorithm isn't enabled");
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +#endif
> +
>   #endif
> diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
> index 9d85b6c11c6b..83fde9e974e3 100644
> --- a/fs/erofs/decompressor.c
> +++ b/fs/erofs/decompressor.c
> @@ -406,6 +406,13 @@ const struct z_erofs_decompressor erofs_decompressors[] = {
>   		.name = "zstd"
>   	},
>   #endif
> +#ifdef CONFIG_EROFS_FS_ZIP_CRYPTO
> +	[Z_EROFS_COMPRESSION_CRYPTO] = {
> +		.config = z_erofs_load_crypto_config,
> +		.decompress = z_erofs_crypto_decompress,
> +		.name = "crypto"
> +	},
> +#endif
>   };
>   
>   int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb)
> diff --git a/fs/erofs/decompressor_cryptor.c b/fs/erofs/decompressor_cryptor.c
> new file mode 100644
> index 000000000000..87df4d285ad1
> --- /dev/null
> +++ b/fs/erofs/decompressor_cryptor.c
> @@ -0,0 +1,306 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
> + */
> +#include <linux/types.h>
> +#include <linux/vmalloc.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/highmem.h>
> +#include <linux/xz.h>
> +#include <linux/module.h>
> +#include <linux/crypto.h>
> +#include "compress.h"
> +#include "internal.h"
> +
> +static int crypto_max_distance_pages;
> +
> +int z_erofs_load_crypto_config(struct super_block *sb,
> +			       struct erofs_super_block *dsb,
> +			       void *data, int size)
> +{
> +	struct erofs_sb_info *sbi;
> +	struct z_erofs_crypto_cfgs *crypto = (struct z_erofs_crypto_cfgs *)data;
> +	int max_pages;
> +
> +	sbi = EROFS_SB(sb);
> +	if (!sbi)
> +		return -EINVAL;
> +
> +	if (sbi->crypto) {
> +		erofs_err(sb, "already have crypto\n");
> +		return -EINVAL;
> +	}
> +	if (crypto) {
> +		max_pages = BIT(crypto->max_distance) / PAGE_SIZE;
> +		if (max_pages > CONFIG_EROFS_CRYPTO_MAX_DISTANCE_PAGES) {
> +			erofs_err(sb, "bad max distance:%d\n", max_pages);
> +			return -EINVAL;
> +		}
> +
> +		if (max_pages > crypto_max_distance_pages)
> +			crypto_max_distance_pages = max_pages;
> +		sbi->crypto = crypto_alloc_comp(crypto->crypto_name, 0, 0);
> +		if (IS_ERR(sbi->crypto)) {
> +			erofs_err(sb, "failed to alloc cryto %s\n",
> +				  crypto->crypto_name);
> +			return PTR_ERR(sbi->crypto);
> +		}
> +		erofs_info(sb, "max pcluster:%d, distance:%d, %d, crypto:%s\n",
> +			   crypto->max_pclusterblks,
> +			   crypto->max_distance, crypto_max_distance_pages,
> +			   crypto->crypto_name);
> +		return z_erofs_gbuf_growsize(crypto_max_distance_pages);

That is optimized for LZ4,  I don't think it's useful for hardware accelerators.


> +	} else {
> +		return -EINVAL;
> +	}
> +}
> +
> +static void *z_erofs_crypto_handle_inplace_io(struct z_erofs_decompress_req *rq,
> +					      void *inpage,
> +					      unsigned int *inputmargin,
> +					      int *maptype,
> +					      bool support_0padding)
> +{
> +	unsigned int nrpages_in, nrpages_out;

...


Same here.

> +	return src;
> +}
> +
> +static int z_erofs_crypto_decompress_mem(struct z_erofs_decompress_req *rq, u8 *out)
> +{

..
Same here.

> +	return ret;
> +}
> +
> +/*
> + * Fill all gaps with bounce pages if it's a sparse page list. Also check if
> + * all physical pages are consecutive, which can be seen for moderate CR.
> + */
> +static int z_erofs_crypto_prepare_dstpages(struct z_erofs_decompress_req *rq,
> +					   struct page **pagepool)
> +{


..
Same here.


> +	}
> +	return kaddr ? 1 : 0;
> +}
> +

...

> diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
> index 6c0c270c42e1..993b7a1b656f 100644
> --- a/fs/erofs/erofs_fs.h
> +++ b/fs/erofs/erofs_fs.h
> @@ -297,6 +297,10 @@ enum {
>   	Z_EROFS_COMPRESSION_LZMA	= 1,
>   	Z_EROFS_COMPRESSION_DEFLATE	= 2,
>   	Z_EROFS_COMPRESSION_ZSTD	= 3,
> +#ifdef CONFIG_EROFS_FS_ZIP_CRYPTO
> +	/* for generic crypto framework */
> +	Z_EROFS_COMPRESSION_CRYPTO	= 4,
> +#endif

crypto is NOT a new algorithm, please maintain a mapping
(crypto decompressor <-> algorithm) with existing algrithms.

>   	Z_EROFS_COMPRESSION_MAX
>   };
>   #define Z_EROFS_ALL_COMPR_ALGS		((1 << Z_EROFS_COMPRESSION_MAX) - 1)
> @@ -330,6 +334,16 @@ struct z_erofs_zstd_cfgs {
>   	u8 reserved[4];
>   } __packed;
>   
> +#ifdef CONFIG_EROFS_FS_ZIP_CRYPTO
> +/* 16 bytes */
> +struct z_erofs_crypto_cfgs {
> +	char   crypto_name[8];
> +	__le16 max_distance;
> +	__le16 max_pclusterblks;
> +	u8     reserved[4];
> +} __packed;
> +#endif

Same here, no needed.

Thanks,
Gao Xiang


More information about the Linux-erofs mailing list