~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/ubifs/compress.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php