Ignore:
Timestamp:
Sep 12, 2013, 1:32:07 PM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
0282e83
Parents:
78b85286
git-author:
Sebastian Huber <sebastian.huber@…> (09/12/13 13:32:07)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/19/13 11:16:06)
Message:

JFFS2: Add RTEMS support

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libfs/src/jffs2/src/compr.c

    r78b85286 r3c96bee  
    66 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
    77 *                  University of Szeged, Hungary
     8 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
    89 *
    910 * Created by Arjan van de Ven <arjan@infradead.org>
     
    1617
    1718#include "compr.h"
    18 
    19 static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
    20 
    21 /* Available compressors are on this list */
    22 static LIST_HEAD(jffs2_compressor_list);
    23 
    24 /* Actual compression mode */
    25 static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
    26 
    27 /* Statistics for blocks stored without compression */
    28 static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
    29 
    30 
    31 /*
    32  * Return 1 to use this compression
    33  */
    34 static int jffs2_is_best_compression(struct jffs2_compressor *this,
    35                 struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
    36 {
    37         switch (jffs2_compression_mode) {
    38         case JFFS2_COMPR_MODE_SIZE:
    39                 if (bestsize > size)
    40                         return 1;
    41                 return 0;
    42         case JFFS2_COMPR_MODE_FAVOURLZO:
    43                 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
    44                         return 1;
    45                 if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
    46                         return 1;
    47                 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
    48                         return 1;
    49                 if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
    50                         return 1;
    51 
    52                 return 0;
    53         }
    54         /* Shouldn't happen */
    55         return 0;
    56 }
    57 
    58 /*
    59  * jffs2_selected_compress:
    60  * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
    61  *      If 0, just take the first available compression mode.
    62  * @data_in: Pointer to uncompressed data
    63  * @cpage_out: Pointer to returned pointer to buffer for compressed data
    64  * @datalen: On entry, holds the amount of data available for compression.
    65  *      On exit, expected to hold the amount of data actually compressed.
    66  * @cdatalen: On entry, holds the amount of space available for compressed
    67  *      data. On exit, expected to hold the actual size of the compressed
    68  *      data.
    69  *
    70  * Returns: the compression type used.  Zero is used to show that the data
    71  * could not be compressed; probably because we couldn't find the requested
    72  * compression mode.
    73  */
    74 static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
    75                 unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
    76 {
    77         struct jffs2_compressor *this;
    78         int err, ret = JFFS2_COMPR_NONE;
    79         uint32_t orig_slen, orig_dlen;
    80         char *output_buf;
    81 
    82         output_buf = kmalloc(*cdatalen, GFP_KERNEL);
    83         if (!output_buf) {
    84                 pr_warn("No memory for compressor allocation. Compression failed.\n");
    85                 return ret;
    86         }
    87         orig_slen = *datalen;
    88         orig_dlen = *cdatalen;
    89         spin_lock(&jffs2_compressor_list_lock);
    90         list_for_each_entry(this, &jffs2_compressor_list, list) {
    91                 /* Skip decompress-only and disabled modules */
    92                 if (!this->compress || this->disabled)
    93                         continue;
    94 
    95                 /* Skip if not the desired compression type */
    96                 if (compr && (compr != this->compr))
    97                         continue;
    98 
    99                 /*
    100                  * Either compression type was unspecified, or we found our
    101                  * compressor; either way, we're good to go.
    102                  */
    103                 this->usecount++;
    104                 spin_unlock(&jffs2_compressor_list_lock);
    105 
    106                 *datalen  = orig_slen;
    107                 *cdatalen = orig_dlen;
    108                 err = this->compress(data_in, output_buf, datalen, cdatalen);
    109 
    110                 spin_lock(&jffs2_compressor_list_lock);
    111                 this->usecount--;
    112                 if (!err) {
    113                         /* Success */
    114                         ret = this->compr;
    115                         this->stat_compr_blocks++;
    116                         this->stat_compr_orig_size += *datalen;
    117                         this->stat_compr_new_size += *cdatalen;
    118                         break;
    119                 }
    120         }
    121         spin_unlock(&jffs2_compressor_list_lock);
    122         if (ret == JFFS2_COMPR_NONE)
    123                 kfree(output_buf);
    124         else
    125                 *cpage_out = output_buf;
    126 
    127         return ret;
    128 }
    12919
    13020/* jffs2_compress:
     
    15040                        uint32_t *datalen, uint32_t *cdatalen)
    15141{
    152         int ret = JFFS2_COMPR_NONE;
    153         int mode, compr_ret;
    154         struct jffs2_compressor *this, *best=NULL;
    155         unsigned char *output_buf = NULL, *tmp_buf;
    156         uint32_t orig_slen, orig_dlen;
    157         uint32_t best_slen=0, best_dlen=0;
     42        struct super_block *sb = OFNI_BS_2SFFJ(c);
     43        rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
     44        int ret;
    15845
    159         if (c->mount_opts.override_compr)
    160                 mode = c->mount_opts.compr;
    161         else
    162                 mode = jffs2_compression_mode;
    163 
    164         switch (mode) {
    165         case JFFS2_COMPR_MODE_NONE:
    166                 break;
    167         case JFFS2_COMPR_MODE_PRIORITY:
    168                 ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
    169                                 cdatalen);
    170                 break;
    171         case JFFS2_COMPR_MODE_SIZE:
    172         case JFFS2_COMPR_MODE_FAVOURLZO:
    173                 orig_slen = *datalen;
    174                 orig_dlen = *cdatalen;
    175                 spin_lock(&jffs2_compressor_list_lock);
    176                 list_for_each_entry(this, &jffs2_compressor_list, list) {
    177                         /* Skip decompress-only backwards-compatibility and disabled modules */
    178                         if ((!this->compress)||(this->disabled))
    179                                 continue;
    180                         /* Allocating memory for output buffer if necessary */
    181                         if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
    182                                 spin_unlock(&jffs2_compressor_list_lock);
    183                                 kfree(this->compr_buf);
    184                                 spin_lock(&jffs2_compressor_list_lock);
    185                                 this->compr_buf_size=0;
    186                                 this->compr_buf=NULL;
    187                         }
    188                         if (!this->compr_buf) {
    189                                 spin_unlock(&jffs2_compressor_list_lock);
    190                                 tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
    191                                 spin_lock(&jffs2_compressor_list_lock);
    192                                 if (!tmp_buf) {
    193                                         pr_warn("No memory for compressor allocation. (%d bytes)\n",
    194                                                 orig_slen);
    195                                         continue;
    196                                 }
    197                                 else {
    198                                         this->compr_buf = tmp_buf;
    199                                         this->compr_buf_size = orig_slen;
    200                                 }
    201                         }
    202                         this->usecount++;
    203                         spin_unlock(&jffs2_compressor_list_lock);
    204                         *datalen  = orig_slen;
    205                         *cdatalen = orig_dlen;
    206                         compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
    207                         spin_lock(&jffs2_compressor_list_lock);
    208                         this->usecount--;
    209                         if (!compr_ret) {
    210                                 if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
    211                                                 && (*cdatalen < *datalen)) {
    212                                         best_dlen = *cdatalen;
    213                                         best_slen = *datalen;
    214                                         best = this;
    215                                 }
    216                         }
    217                 }
    218                 if (best_dlen) {
    219                         *cdatalen = best_dlen;
    220                         *datalen  = best_slen;
    221                         output_buf = best->compr_buf;
    222                         best->compr_buf = NULL;
    223                         best->compr_buf_size = 0;
    224                         best->stat_compr_blocks++;
    225                         best->stat_compr_orig_size += best_slen;
    226                         best->stat_compr_new_size  += best_dlen;
    227                         ret = best->compr;
    228                         *cpage_out = output_buf;
    229                 }
    230                 spin_unlock(&jffs2_compressor_list_lock);
    231                 break;
    232         case JFFS2_COMPR_MODE_FORCELZO:
    233                 ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
    234                                 cpage_out, datalen, cdatalen);
    235                 break;
    236         case JFFS2_COMPR_MODE_FORCEZLIB:
    237                 ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
    238                                 cpage_out, datalen, cdatalen);
    239                 break;
    240         default:
    241                 pr_err("unknown compression mode\n");
     46        if (cc != NULL) {
     47                *cpage_out = &cc->buffer[0];
     48                ret = (*cc->compress)(cc, data_in, *cpage_out, datalen, cdatalen);
     49        } else {
     50                ret = JFFS2_COMPR_NONE;
    24251        }
    24352
     
    24554                *cpage_out = data_in;
    24655                *datalen = *cdatalen;
    247                 none_stat_compr_blocks++;
    248                 none_stat_compr_size += *datalen;
    24956        }
    25057        return ret;
     
    25562                     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
    25663{
    257         struct jffs2_compressor *this;
    258         int ret;
     64        struct super_block *sb = OFNI_BS_2SFFJ(c);
     65        rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
    25966
    26067        /* Older code had a bug where it would write non-zero 'usercompr'
     
    26774                /* This should be special-cased elsewhere, but we might as well deal with it */
    26875                memcpy(data_out, cdata_in, datalen);
    269                 none_stat_decompr_blocks++;
    27076                break;
    27177        case JFFS2_COMPR_ZERO:
     
    27379                break;
    27480        default:
    275                 spin_lock(&jffs2_compressor_list_lock);
    276                 list_for_each_entry(this, &jffs2_compressor_list, list) {
    277                         if (comprtype == this->compr) {
    278                                 this->usecount++;
    279                                 spin_unlock(&jffs2_compressor_list_lock);
    280                                 ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
    281                                 spin_lock(&jffs2_compressor_list_lock);
    282                                 if (ret) {
    283                                         pr_warn("Decompressor \"%s\" returned %d\n",
    284                                                 this->name, ret);
    285                                 }
    286                                 else {
    287                                         this->stat_decompr_blocks++;
    288                                 }
    289                                 this->usecount--;
    290                                 spin_unlock(&jffs2_compressor_list_lock);
    291                                 return ret;
    292                         }
     81                if (cc != NULL) {
     82                        return (*cc->decompress)(cc, comprtype, cdata_in, data_out, cdatalen, datalen);
     83                } else {
     84                        return -EIO;
    29385                }
    294                 pr_warn("compression type 0x%02x not available\n", comprtype);
    295                 spin_unlock(&jffs2_compressor_list_lock);
    296                 return -EIO;
    29786        }
    29887        return 0;
    29988}
    300 
    301 int jffs2_register_compressor(struct jffs2_compressor *comp)
    302 {
    303         struct jffs2_compressor *this;
    304 
    305         if (!comp->name) {
    306                 pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
    307                 return -1;
    308         }
    309         comp->compr_buf_size=0;
    310         comp->compr_buf=NULL;
    311         comp->usecount=0;
    312         comp->stat_compr_orig_size=0;
    313         comp->stat_compr_new_size=0;
    314         comp->stat_compr_blocks=0;
    315         comp->stat_decompr_blocks=0;
    316         jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
    317 
    318         spin_lock(&jffs2_compressor_list_lock);
    319 
    320         list_for_each_entry(this, &jffs2_compressor_list, list) {
    321                 if (this->priority < comp->priority) {
    322                         list_add(&comp->list, this->list.prev);
    323                         goto out;
    324                 }
    325         }
    326         list_add_tail(&comp->list, &jffs2_compressor_list);
    327 out:
    328         D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
    329                 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
    330         })
    331 
    332         spin_unlock(&jffs2_compressor_list_lock);
    333 
    334         return 0;
    335 }
    336 
    337 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
    338 {
    339         D2(struct jffs2_compressor *this);
    340 
    341         jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
    342 
    343         spin_lock(&jffs2_compressor_list_lock);
    344 
    345         if (comp->usecount) {
    346                 spin_unlock(&jffs2_compressor_list_lock);
    347                 pr_warn("Compressor module is in use. Unregister failed.\n");
    348                 return -1;
    349         }
    350         list_del(&comp->list);
    351 
    352         D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
    353                 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
    354         })
    355         spin_unlock(&jffs2_compressor_list_lock);
    356         return 0;
    357 }
    358 
    359 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
    360 {
    361         if (orig != comprbuf)
    362                 kfree(comprbuf);
    363 }
    364 
    365 int __init jffs2_compressors_init(void)
    366 {
    367 /* Registering compressors */
    368 #ifdef CONFIG_JFFS2_ZLIB
    369         jffs2_zlib_init();
    370 #endif
    371 #ifdef CONFIG_JFFS2_RTIME
    372         jffs2_rtime_init();
    373 #endif
    374 #ifdef CONFIG_JFFS2_RUBIN
    375         jffs2_rubinmips_init();
    376         jffs2_dynrubin_init();
    377 #endif
    378 #ifdef CONFIG_JFFS2_LZO
    379         jffs2_lzo_init();
    380 #endif
    381 /* Setting default compression mode */
    382 #ifdef CONFIG_JFFS2_CMODE_NONE
    383         jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
    384         jffs2_dbg(1, "default compression mode: none\n");
    385 #else
    386 #ifdef CONFIG_JFFS2_CMODE_SIZE
    387         jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
    388         jffs2_dbg(1, "default compression mode: size\n");
    389 #else
    390 #ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
    391         jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
    392         jffs2_dbg(1, "default compression mode: favourlzo\n");
    393 #else
    394         jffs2_dbg(1, "default compression mode: priority\n");
    395 #endif
    396 #endif
    397 #endif
    398         return 0;
    399 }
    400 
    401 int jffs2_compressors_exit(void)
    402 {
    403 /* Unregistering compressors */
    404 #ifdef CONFIG_JFFS2_LZO
    405         jffs2_lzo_exit();
    406 #endif
    407 #ifdef CONFIG_JFFS2_RUBIN
    408         jffs2_dynrubin_exit();
    409         jffs2_rubinmips_exit();
    410 #endif
    411 #ifdef CONFIG_JFFS2_RTIME
    412         jffs2_rtime_exit();
    413 #endif
    414 #ifdef CONFIG_JFFS2_ZLIB
    415         jffs2_zlib_exit();
    416 #endif
    417         return 0;
    418 }
Note: See TracChangeset for help on using the changeset viewer.