OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [jffs2/] [current/] [src/] [compr.c] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001-2003 Red Hat, Inc.
5
 * Created by Arjan van de Ven <arjanv@redhat.com>
6
 *
7
 * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
8
 *                    University of Szeged, Hungary
9
 *
10
 * For licensing information, see the file 'LICENCE' in this directory.
11
 *
12
 * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $
13
 *
14
 */
15
 
16
#include "compr.h"
17
 
18
static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
19
 
20
/* Available compressors are on this list */
21
static LIST_HEAD(jffs2_compressor_list);
22
 
23
/* Actual compression mode */
24
static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
25
 
26
/* Statistics for blocks stored without compression */
27
static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
28
 
29
/* jffs2_compress:
30
 * @data: Pointer to uncompressed data
31
 * @cdata: Pointer to returned pointer to buffer for compressed data
32
 * @datalen: On entry, holds the amount of data available for compression.
33
 *      On exit, expected to hold the amount of data actually compressed.
34
 * @cdatalen: On entry, holds the amount of space available for compressed
35
 *      data. On exit, expected to hold the actual size of the compressed
36
 *      data.
37
 *
38
 * Returns: Lower byte to be stored with data indicating compression type used.
39
 * Zero is used to show that the data could not be compressed - the
40
 * compressed version was actually larger than the original.
41
 * Upper byte will be used later. (soon)
42
 *
43
 * If the cdata buffer isn't large enough to hold all the uncompressed data,
44
 * jffs2_compress should compress as much as will fit, and should set
45
 * *datalen accordingly to show the amount of data which were compressed.
46
 */
47
uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
48
                             unsigned char *data_in, unsigned char **cpage_out,
49
                             uint32_t *datalen, uint32_t *cdatalen)
50
{
51
        int ret = JFFS2_COMPR_NONE;
52
        int compr_ret;
53
        struct jffs2_compressor *this, *best=NULL;
54
        unsigned char *output_buf = NULL, *tmp_buf;
55
        uint32_t orig_slen, orig_dlen;
56
        uint32_t best_slen=0, best_dlen=0;
57
 
58
        switch (jffs2_compression_mode) {
59
        case JFFS2_COMPR_MODE_NONE:
60
                break;
61
        case JFFS2_COMPR_MODE_PRIORITY:
62
                output_buf = kmalloc(*cdatalen,GFP_KERNEL);
63
                if (!output_buf) {
64
                        printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
65
                        goto out;
66
                }
67
                orig_slen = *datalen;
68
                orig_dlen = *cdatalen;
69
                spin_lock(&jffs2_compressor_list_lock);
70
                list_for_each_entry(this, &jffs2_compressor_list, list) {
71
                        /* Skip decompress-only backwards-compatibility and disabled modules */
72
                        if ((!this->compress)||(this->disabled))
73
                                continue;
74
 
75
                        this->usecount++;
76
                        spin_unlock(&jffs2_compressor_list_lock);
77
                        *datalen  = orig_slen;
78
                        *cdatalen = orig_dlen;
79
                        compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
80
                        spin_lock(&jffs2_compressor_list_lock);
81
                        this->usecount--;
82
                        if (!compr_ret) {
83
                                ret = this->compr;
84
                                this->stat_compr_blocks++;
85
                                this->stat_compr_orig_size += *datalen;
86
                                this->stat_compr_new_size  += *cdatalen;
87
                                break;
88
                        }
89
                }
90
                spin_unlock(&jffs2_compressor_list_lock);
91
                if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
92
                break;
93
        case JFFS2_COMPR_MODE_SIZE:
94
                orig_slen = *datalen;
95
                orig_dlen = *cdatalen;
96
                spin_lock(&jffs2_compressor_list_lock);
97
                list_for_each_entry(this, &jffs2_compressor_list, list) {
98
                        /* Skip decompress-only backwards-compatibility and disabled modules */
99
                        if ((!this->compress)||(this->disabled))
100
                                continue;
101
                        /* Allocating memory for output buffer if necessary */
102
                        if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
103
                                spin_unlock(&jffs2_compressor_list_lock);
104
                                kfree(this->compr_buf);
105
                                spin_lock(&jffs2_compressor_list_lock);
106
                                this->compr_buf_size=0;
107
                                this->compr_buf=NULL;
108
                        }
109
                        if (!this->compr_buf) {
110
                                spin_unlock(&jffs2_compressor_list_lock);
111
                                tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
112
                                spin_lock(&jffs2_compressor_list_lock);
113
                                if (!tmp_buf) {
114
                                        printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
115
                                        continue;
116
                                }
117
                                else {
118
                                        this->compr_buf = tmp_buf;
119
                                        this->compr_buf_size = orig_dlen;
120
                                }
121
                        }
122
                        this->usecount++;
123
                        spin_unlock(&jffs2_compressor_list_lock);
124
                        *datalen  = orig_slen;
125
                        *cdatalen = orig_dlen;
126
                        compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
127
                        spin_lock(&jffs2_compressor_list_lock);
128
                        this->usecount--;
129
                        if (!compr_ret) {
130
                                if ((!best_dlen)||(best_dlen>*cdatalen)) {
131
                                        best_dlen = *cdatalen;
132
                                        best_slen = *datalen;
133
                                        best = this;
134
                                }
135
                        }
136
                }
137
                if (best_dlen) {
138
                        *cdatalen = best_dlen;
139
                        *datalen  = best_slen;
140
                        output_buf = best->compr_buf;
141
                        best->compr_buf = NULL;
142
                        best->compr_buf_size = 0;
143
                        best->stat_compr_blocks++;
144
                        best->stat_compr_orig_size += best_slen;
145
                        best->stat_compr_new_size  += best_dlen;
146
                        ret = best->compr;
147
                }
148
                spin_unlock(&jffs2_compressor_list_lock);
149
                break;
150
        default:
151
                printk(KERN_ERR "JFFS2: unknow compression mode.\n");
152
        }
153
 out:
154
        if (ret == JFFS2_COMPR_NONE) {
155
                *cpage_out = data_in;
156
                *datalen = *cdatalen;
157
                none_stat_compr_blocks++;
158
                none_stat_compr_size += *datalen;
159
        }
160
        else {
161
                *cpage_out = output_buf;
162
        }
163
        return ret;
164
}
165
 
166
int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
167
                     uint16_t comprtype, unsigned char *cdata_in,
168
                     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
169
{
170
        struct jffs2_compressor *this;
171
        int ret;
172
 
173
        /* Older code had a bug where it would write non-zero 'usercompr'
174
           fields. Deal with it. */
175
        if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB)
176
                comprtype &= 0xff;
177
 
178
        switch (comprtype & 0xff) {
179
        case JFFS2_COMPR_NONE:
180
                /* This should be special-cased elsewhere, but we might as well deal with it */
181
                memcpy(data_out, cdata_in, datalen);
182
                none_stat_decompr_blocks++;
183
                break;
184
        case JFFS2_COMPR_ZERO:
185
                memset(data_out, 0, datalen);
186
                break;
187
        default:
188
                spin_lock(&jffs2_compressor_list_lock);
189
                list_for_each_entry(this, &jffs2_compressor_list, list) {
190
                        if (comprtype == this->compr) {
191
                                this->usecount++;
192
                                spin_unlock(&jffs2_compressor_list_lock);
193
                                ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
194
                                spin_lock(&jffs2_compressor_list_lock);
195
                                if (ret) {
196
                                        printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
197
                                }
198
                                else {
199
                                        this->stat_decompr_blocks++;
200
                                }
201
                                this->usecount--;
202
                                spin_unlock(&jffs2_compressor_list_lock);
203
                                return ret;
204
                        }
205
                }
206
                printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
207
                spin_unlock(&jffs2_compressor_list_lock);
208
                return -EIO;
209
        }
210
        return 0;
211
}
212
 
213
int jffs2_register_compressor(struct jffs2_compressor *comp)
214
{
215
        struct jffs2_compressor *this;
216
 
217
        if (!comp->name) {
218
                printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
219
                return -1;
220
        }
221
        comp->compr_buf_size=0;
222
        comp->compr_buf=NULL;
223
        comp->usecount=0;
224
        comp->stat_compr_orig_size=0;
225
        comp->stat_compr_new_size=0;
226
        comp->stat_compr_blocks=0;
227
        comp->stat_decompr_blocks=0;
228
        D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
229
 
230
        spin_lock(&jffs2_compressor_list_lock);
231
 
232
        list_for_each_entry(this, &jffs2_compressor_list, list) {
233
                if (this->priority < comp->priority) {
234
                        list_add(&comp->list, this->list.prev);
235
                        goto out;
236
                }
237
        }
238
        list_add_tail(&comp->list, &jffs2_compressor_list);
239
out:
240
        D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
241
                printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
242
        })
243
 
244
        spin_unlock(&jffs2_compressor_list_lock);
245
 
246
        return 0;
247
}
248
 
249
int jffs2_unregister_compressor(struct jffs2_compressor *comp)
250
{
251
        D2(struct jffs2_compressor *this;)
252
 
253
        D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
254
 
255
        spin_lock(&jffs2_compressor_list_lock);
256
 
257
        if (comp->usecount) {
258
                spin_unlock(&jffs2_compressor_list_lock);
259
                printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
260
                return -1;
261
        }
262
        list_del(&comp->list);
263
 
264
        D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
265
                printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
266
        })
267
        spin_unlock(&jffs2_compressor_list_lock);
268
        return 0;
269
}
270
 
271
#ifdef CONFIG_JFFS2_PROC
272
 
273
#define JFFS2_STAT_BUF_SIZE 16000
274
 
275
char *jffs2_list_compressors(void)
276
{
277
        struct jffs2_compressor *this;
278
        char *buf, *act_buf;
279
 
280
        act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
281
        list_for_each_entry(this, &jffs2_compressor_list, list) {
282
                act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority);
283
                if ((this->disabled)||(!this->compress))
284
                        act_buf += sprintf(act_buf,"disabled");
285
                else
286
                        act_buf += sprintf(act_buf,"enabled");
287
                act_buf += sprintf(act_buf,"\n");
288
        }
289
        return buf;
290
}
291
 
292
char *jffs2_stats(void)
293
{
294
        struct jffs2_compressor *this;
295
        char *buf, *act_buf;
296
 
297
        act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
298
 
299
        act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n");
300
        act_buf += sprintf(act_buf,"%10s   ","none");
301
        act_buf += sprintf(act_buf,"compr: %d blocks (%d)  decompr: %d blocks\n", none_stat_compr_blocks,
302
                           none_stat_compr_size, none_stat_decompr_blocks);
303
        spin_lock(&jffs2_compressor_list_lock);
304
        list_for_each_entry(this, &jffs2_compressor_list, list) {
305
                act_buf += sprintf(act_buf,"%10s ",this->name);
306
                if ((this->disabled)||(!this->compress))
307
                        act_buf += sprintf(act_buf,"- ");
308
                else
309
                        act_buf += sprintf(act_buf,"+ ");
310
                act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d)  decompr: %d blocks ", this->stat_compr_blocks,
311
                                   this->stat_compr_new_size, this->stat_compr_orig_size,
312
                                   this->stat_decompr_blocks);
313
                act_buf += sprintf(act_buf,"\n");
314
        }
315
        spin_unlock(&jffs2_compressor_list_lock);
316
 
317
        return buf;
318
}
319
 
320
char *jffs2_get_compression_mode_name(void)
321
{
322
        switch (jffs2_compression_mode) {
323
        case JFFS2_COMPR_MODE_NONE:
324
                return "none";
325
        case JFFS2_COMPR_MODE_PRIORITY:
326
                return "priority";
327
        case JFFS2_COMPR_MODE_SIZE:
328
                return "size";
329
        }
330
        return "unkown";
331
}
332
 
333
int jffs2_set_compression_mode_name(const char *name)
334
{
335
        if (!strcmp("none",name)) {
336
                jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
337
                return 0;
338
        }
339
        if (!strcmp("priority",name)) {
340
                jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
341
                return 0;
342
        }
343
        if (!strcmp("size",name)) {
344
                jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
345
                return 0;
346
        }
347
        return 1;
348
}
349
 
350
static int jffs2_compressor_Xable(const char *name, int disabled)
351
{
352
        struct jffs2_compressor *this;
353
        spin_lock(&jffs2_compressor_list_lock);
354
        list_for_each_entry(this, &jffs2_compressor_list, list) {
355
                if (!strcmp(this->name, name)) {
356
                        this->disabled = disabled;
357
                        spin_unlock(&jffs2_compressor_list_lock);
358
                        return 0;
359
                }
360
        }
361
        spin_unlock(&jffs2_compressor_list_lock);
362
        printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
363
        return 1;
364
}
365
 
366
int jffs2_enable_compressor_name(const char *name)
367
{
368
        return jffs2_compressor_Xable(name, 0);
369
}
370
 
371
int jffs2_disable_compressor_name(const char *name)
372
{
373
        return jffs2_compressor_Xable(name, 1);
374
}
375
 
376
int jffs2_set_compressor_priority(const char *name, int priority)
377
{
378
        struct jffs2_compressor *this,*comp;
379
        spin_lock(&jffs2_compressor_list_lock);
380
        list_for_each_entry(this, &jffs2_compressor_list, list) {
381
                if (!strcmp(this->name, name)) {
382
                        this->priority = priority;
383
                        comp = this;
384
                        goto reinsert;
385
                }
386
        }
387
        spin_unlock(&jffs2_compressor_list_lock);
388
        printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
389
        return 1;
390
reinsert:
391
        /* list is sorted in the order of priority, so if
392
           we change it we have to reinsert it into the
393
           good place */
394
        list_del(&comp->list);
395
        list_for_each_entry(this, &jffs2_compressor_list, list) {
396
                if (this->priority < comp->priority) {
397
                        list_add(&comp->list, this->list.prev);
398
                        spin_unlock(&jffs2_compressor_list_lock);
399
                        return 0;
400
                }
401
        }
402
        list_add_tail(&comp->list, &jffs2_compressor_list);
403
        spin_unlock(&jffs2_compressor_list_lock);
404
        return 0;
405
}
406
 
407
#endif
408
 
409
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
410
{
411
        if (orig != comprbuf)
412
                kfree(comprbuf);
413
}
414
 
415
int jffs2_compressors_init(void)
416
{
417
/* Registering compressors */
418
#ifdef CONFIG_JFFS2_ZLIB
419
        jffs2_zlib_init();
420
#endif
421
#ifdef CONFIG_JFFS2_RTIME
422
        jffs2_rtime_init();
423
#endif
424
#ifdef CONFIG_JFFS2_RUBIN
425
        jffs2_rubinmips_init();
426
        jffs2_dynrubin_init();
427
#endif
428
/* Setting default compression mode */
429
#ifdef CONFIG_JFFS2_CMODE_NONE
430
        jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
431
        D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
432
#else
433
#ifdef CONFIG_JFFS2_CMODE_SIZE
434
        jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
435
        D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
436
#else
437
        D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
438
#endif
439
#endif
440
        return 0;
441
}
442
 
443
int jffs2_compressors_exit(void)
444
{
445
/* Unregistering compressors */
446
#ifdef CONFIG_JFFS2_RUBIN
447
        jffs2_dynrubin_exit();
448
        jffs2_rubinmips_exit();
449
#endif
450
#ifdef CONFIG_JFFS2_RTIME
451
        jffs2_rtime_exit();
452
#endif
453
#ifdef CONFIG_JFFS2_ZLIB
454
        jffs2_zlib_exit();
455
#endif
456
        return 0;
457
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.