cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

compress.c (6780B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of UBIFS.
      4 *
      5 * Copyright (C) 2006-2008 Nokia Corporation.
      6 * Copyright (C) 2006, 2007 University of Szeged, Hungary
      7 *
      8 * Authors: Adrian Hunter
      9 *          Artem Bityutskiy (Битюцкий Артём)
     10 *          Zoltan Sogor
     11 */
     12
     13/*
     14 * This file provides a single place to access to compression and
     15 * decompression.
     16 */
     17
     18#include <linux/crypto.h>
     19#include "ubifs.h"
     20
     21/* Fake description object for the "none" compressor */
     22static struct ubifs_compressor none_compr = {
     23	.compr_type = UBIFS_COMPR_NONE,
     24	.name = "none",
     25	.capi_name = "",
     26};
     27
     28#ifdef CONFIG_UBIFS_FS_LZO
     29static DEFINE_MUTEX(lzo_mutex);
     30
     31static struct ubifs_compressor lzo_compr = {
     32	.compr_type = UBIFS_COMPR_LZO,
     33	.comp_mutex = &lzo_mutex,
     34	.name = "lzo",
     35	.capi_name = "lzo",
     36};
     37#else
     38static struct ubifs_compressor lzo_compr = {
     39	.compr_type = UBIFS_COMPR_LZO,
     40	.name = "lzo",
     41};
     42#endif
     43
     44#ifdef CONFIG_UBIFS_FS_ZLIB
     45static DEFINE_MUTEX(deflate_mutex);
     46static DEFINE_MUTEX(inflate_mutex);
     47
     48static struct ubifs_compressor zlib_compr = {
     49	.compr_type = UBIFS_COMPR_ZLIB,
     50	.comp_mutex = &deflate_mutex,
     51	.decomp_mutex = &inflate_mutex,
     52	.name = "zlib",
     53	.capi_name = "deflate",
     54};
     55#else
     56static struct ubifs_compressor zlib_compr = {
     57	.compr_type = UBIFS_COMPR_ZLIB,
     58	.name = "zlib",
     59};
     60#endif
     61
     62#ifdef CONFIG_UBIFS_FS_ZSTD
     63static DEFINE_MUTEX(zstd_enc_mutex);
     64static DEFINE_MUTEX(zstd_dec_mutex);
     65
     66static struct ubifs_compressor zstd_compr = {
     67	.compr_type = UBIFS_COMPR_ZSTD,
     68	.comp_mutex = &zstd_enc_mutex,
     69	.decomp_mutex = &zstd_dec_mutex,
     70	.name = "zstd",
     71	.capi_name = "zstd",
     72};
     73#else
     74static struct ubifs_compressor zstd_compr = {
     75	.compr_type = UBIFS_COMPR_ZSTD,
     76	.name = "zstd",
     77};
     78#endif
     79
     80/* All UBIFS compressors */
     81struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
     82
     83/**
     84 * ubifs_compress - compress data.
     85 * @in_buf: data to compress
     86 * @in_len: length of the data to compress
     87 * @out_buf: output buffer where compressed data should be stored
     88 * @out_len: output buffer length is returned here
     89 * @compr_type: type of compression to use on enter, actually used compression
     90 *              type on exit
     91 *
     92 * This function compresses input buffer @in_buf of length @in_len and stores
     93 * the result in the output buffer @out_buf and the resulting length in
     94 * @out_len. If the input buffer does not compress, it is just copied to the
     95 * @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if
     96 * compression error occurred.
     97 *
     98 * Note, if the input buffer was not compressed, it is copied to the output
     99 * buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
    100 */
    101void ubifs_compress(const struct ubifs_info *c, const void *in_buf,
    102		    int in_len, void *out_buf, int *out_len, int *compr_type)
    103{
    104	int err;
    105	struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
    106
    107	if (*compr_type == UBIFS_COMPR_NONE)
    108		goto no_compr;
    109
    110	/* If the input data is small, do not even try to compress it */
    111	if (in_len < UBIFS_MIN_COMPR_LEN)
    112		goto no_compr;
    113
    114	if (compr->comp_mutex)
    115		mutex_lock(compr->comp_mutex);
    116	err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
    117				   (unsigned int *)out_len);
    118	if (compr->comp_mutex)
    119		mutex_unlock(compr->comp_mutex);
    120	if (unlikely(err)) {
    121		ubifs_warn(c, "cannot compress %d bytes, compressor %s, error %d, leave data uncompressed",
    122			   in_len, compr->name, err);
    123		goto no_compr;
    124	}
    125
    126	/*
    127	 * If the data compressed only slightly, it is better to leave it
    128	 * uncompressed to improve read speed.
    129	 */
    130	if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF)
    131		goto no_compr;
    132
    133	return;
    134
    135no_compr:
    136	memcpy(out_buf, in_buf, in_len);
    137	*out_len = in_len;
    138	*compr_type = UBIFS_COMPR_NONE;
    139}
    140
    141/**
    142 * ubifs_decompress - decompress data.
    143 * @in_buf: data to decompress
    144 * @in_len: length of the data to decompress
    145 * @out_buf: output buffer where decompressed data should
    146 * @out_len: output length is returned here
    147 * @compr_type: type of compression
    148 *
    149 * This function decompresses data from buffer @in_buf into buffer @out_buf.
    150 * The length of the uncompressed data is returned in @out_len. This functions
    151 * returns %0 on success or a negative error code on failure.
    152 */
    153int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
    154		     int in_len, void *out_buf, int *out_len, int compr_type)
    155{
    156	int err;
    157	struct ubifs_compressor *compr;
    158
    159	if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
    160		ubifs_err(c, "invalid compression type %d", compr_type);
    161		return -EINVAL;
    162	}
    163
    164	compr = ubifs_compressors[compr_type];
    165
    166	if (unlikely(!compr->capi_name)) {
    167		ubifs_err(c, "%s compression is not compiled in", compr->name);
    168		return -EINVAL;
    169	}
    170
    171	if (compr_type == UBIFS_COMPR_NONE) {
    172		memcpy(out_buf, in_buf, in_len);
    173		*out_len = in_len;
    174		return 0;
    175	}
    176
    177	if (compr->decomp_mutex)
    178		mutex_lock(compr->decomp_mutex);
    179	err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
    180				     (unsigned int *)out_len);
    181	if (compr->decomp_mutex)
    182		mutex_unlock(compr->decomp_mutex);
    183	if (err)
    184		ubifs_err(c, "cannot decompress %d bytes, compressor %s, error %d",
    185			  in_len, compr->name, err);
    186
    187	return err;
    188}
    189
    190/**
    191 * compr_init - initialize a compressor.
    192 * @compr: compressor description object
    193 *
    194 * This function initializes the requested compressor and returns zero in case
    195 * of success or a negative error code in case of failure.
    196 */
    197static int __init compr_init(struct ubifs_compressor *compr)
    198{
    199	if (compr->capi_name) {
    200		compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
    201		if (IS_ERR(compr->cc)) {
    202			pr_err("UBIFS error (pid %d): cannot initialize compressor %s, error %ld",
    203			       current->pid, compr->name, PTR_ERR(compr->cc));
    204			return PTR_ERR(compr->cc);
    205		}
    206	}
    207
    208	ubifs_compressors[compr->compr_type] = compr;
    209	return 0;
    210}
    211
    212/**
    213 * compr_exit - de-initialize a compressor.
    214 * @compr: compressor description object
    215 */
    216static void compr_exit(struct ubifs_compressor *compr)
    217{
    218	if (compr->capi_name)
    219		crypto_free_comp(compr->cc);
    220	return;
    221}
    222
    223/**
    224 * ubifs_compressors_init - initialize UBIFS compressors.
    225 *
    226 * This function initializes the compressor which were compiled in. Returns
    227 * zero in case of success and a negative error code in case of failure.
    228 */
    229int __init ubifs_compressors_init(void)
    230{
    231	int err;
    232
    233	err = compr_init(&lzo_compr);
    234	if (err)
    235		return err;
    236
    237	err = compr_init(&zstd_compr);
    238	if (err)
    239		goto out_lzo;
    240
    241	err = compr_init(&zlib_compr);
    242	if (err)
    243		goto out_zstd;
    244
    245	ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
    246	return 0;
    247
    248out_zstd:
    249	compr_exit(&zstd_compr);
    250out_lzo:
    251	compr_exit(&lzo_compr);
    252	return err;
    253}
    254
    255/**
    256 * ubifs_compressors_exit - de-initialize UBIFS compressors.
    257 */
    258void ubifs_compressors_exit(void)
    259{
    260	compr_exit(&lzo_compr);
    261	compr_exit(&zlib_compr);
    262	compr_exit(&zstd_compr);
    263}