embox

Форк
0
/
compr.c 
453 строки · 12.9 Кб
1
/*
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
 * @date: 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
	int ret = JFFS2_COMPR_NONE;
51
	int compr_ret;
52
	struct jffs2_compressor *this, *best=NULL;
53
	unsigned char *output_buf = NULL, *tmp_buf;
54
	uint32_t orig_slen, orig_dlen;
55
	uint32_t best_slen=0, best_dlen=0;
56

57
	switch (jffs2_compression_mode) {
58
	case JFFS2_COMPR_MODE_NONE:
59
		break;
60
	case JFFS2_COMPR_MODE_PRIORITY:
61
		output_buf = kmalloc(*cdatalen,GFP_KERNEL);
62
		if (!output_buf) {
63
			printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
64
			goto out;
65
		}
66
		orig_slen = *datalen;
67
		orig_dlen = *cdatalen;
68
		spin_lock(&jffs2_compressor_list_lock);
69
		list_for_each_entry(this, &jffs2_compressor_list, list) {
70
			/* Skip decompress-only backwards-compatibility and disabled modules */
71
			if ((!this->compress)||(this->disabled)) {
72
				continue;
73
			}
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,
80
					output_buf, datalen, cdatalen, NULL);
81
			spin_lock(&jffs2_compressor_list_lock);
82
			this->usecount--;
83
			if (!compr_ret) {
84
				ret = this->compr;
85
				this->stat_compr_blocks++;
86
				this->stat_compr_orig_size += *datalen;
87
				this->stat_compr_new_size  += *cdatalen;
88
				break;
89
			}
90
		}
91
		spin_unlock(&jffs2_compressor_list_lock);
92
		if (ret == JFFS2_COMPR_NONE) {
93
			kfree(output_buf);
94
		}
95
		break;
96
	case JFFS2_COMPR_MODE_SIZE:
97
		orig_slen = *datalen;
98
		orig_dlen = *cdatalen;
99
		spin_lock(&jffs2_compressor_list_lock);
100
		list_for_each_entry(this, &jffs2_compressor_list, list) {
101
			/* Skip decompress-only backwards-compatibility and disabled modules */
102
			if ((!this->compress)||(this->disabled)) {
103
				continue;
104
			}
105
			/* Allocating memory for output buffer if necessary */
106
			if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
107
				spin_unlock(&jffs2_compressor_list_lock);
108
				kfree(this->compr_buf);
109
				spin_lock(&jffs2_compressor_list_lock);
110
				this->compr_buf_size=0;
111
				this->compr_buf=NULL;
112
			}
113
			if (!this->compr_buf) {
114
				spin_unlock(&jffs2_compressor_list_lock);
115
				tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
116
				spin_lock(&jffs2_compressor_list_lock);
117
				if (!tmp_buf) {
118
					printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
119
					continue;
120
				} else {
121
					this->compr_buf = tmp_buf;
122
					this->compr_buf_size = orig_dlen;
123
				}
124
			}
125
			this->usecount++;
126
			spin_unlock(&jffs2_compressor_list_lock);
127
			*datalen  = orig_slen;
128
			*cdatalen = orig_dlen;
129
			compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
130
			spin_lock(&jffs2_compressor_list_lock);
131
			this->usecount--;
132
			if (!compr_ret) {
133
				if ((!best_dlen)||(best_dlen>*cdatalen)) {
134
					best_dlen = *cdatalen;
135
					best_slen = *datalen;
136
					best = this;
137
				}
138
			}
139
		}
140
		if (best_dlen) {
141
			*cdatalen = best_dlen;
142
			*datalen  = best_slen;
143
			output_buf = best->compr_buf;
144
			best->compr_buf = NULL;
145
			best->compr_buf_size = 0;
146
			best->stat_compr_blocks++;
147
			best->stat_compr_orig_size += best_slen;
148
			best->stat_compr_new_size  += best_dlen;
149
			ret = best->compr;
150
		}
151
		spin_unlock(&jffs2_compressor_list_lock);
152
		break;
153
	default:
154
		printk(KERN_ERR "JFFS2: unknow compression mode.\n");
155
		break;
156
	}
157
	out:
158
	if (ret == JFFS2_COMPR_NONE) {
159
		*cpage_out = data_in;
160
		*datalen = *cdatalen;
161
		none_stat_compr_blocks++;
162
		none_stat_compr_size += *datalen;
163
	} else {
164
		*cpage_out = output_buf;
165
	}
166
	return ret;
167
}
168

169
int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
170
		     uint16_t comprtype, unsigned char *cdata_in,
171
		     unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) {
172
        struct jffs2_compressor *this;
173
        int ret;
174

175
	/* Older code had a bug where it would write non-zero 'usercompr'
176
	 * fields. Deal with it.
177
	 */
178
	if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB) {
179
		comprtype &= 0xff;
180
	}
181

182
	switch (comprtype & 0xff) {
183
	case JFFS2_COMPR_NONE:
184
		/* This should be special-cased elsewhere, but we might as well deal with it */
185
		memcpy(data_out, cdata_in, datalen);
186
        none_stat_decompr_blocks++;
187
		break;
188
	case JFFS2_COMPR_ZERO:
189
		memset(data_out, 0, datalen);
190
		break;
191
	default:
192
		spin_lock(&jffs2_compressor_list_lock);
193
		list_for_each_entry(this, &jffs2_compressor_list, list) {
194
			if (comprtype == this->compr) {
195
				this->usecount++;
196
				spin_unlock(&jffs2_compressor_list_lock);
197
				ret = this->decompress(cdata_in,
198
						data_out, cdatalen, datalen, NULL);
199
				spin_lock(&jffs2_compressor_list_lock);
200
				if (ret) {
201
					printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
202
				} else {
203
					this->stat_decompr_blocks++;
204
				}
205
				this->usecount--;
206
				spin_unlock(&jffs2_compressor_list_lock);
207
				return ret;
208
			}
209
		}
210
		printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
211
		spin_unlock(&jffs2_compressor_list_lock);
212
		return -EIO;
213
	}
214
	return 0;
215
}
216

217
int jffs2_register_compressor(struct jffs2_compressor *comp) {
218
        struct jffs2_compressor *this;
219

220
	if (!comp->name) {
221
		printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
222
		return -1;
223
	}
224
	comp->compr_buf_size=0;
225
	comp->compr_buf=NULL;
226
	comp->usecount=0;
227
	comp->stat_compr_orig_size=0;
228
	comp->stat_compr_new_size=0;
229
	comp->stat_compr_blocks=0;
230
	comp->stat_decompr_blocks=0;
231
	D1(printk( "Registering JFFS2 compressor \"%s\"\n", comp->name));
232

233
	spin_lock(&jffs2_compressor_list_lock);
234

235
	list_for_each_entry(this, &jffs2_compressor_list, list) {
236
		if (this->priority < comp->priority) {
237
			list_add(&comp->list, this->list.prev);
238
			goto out;
239
		}
240
	}
241
	list_add_tail(&comp->list, &jffs2_compressor_list);
242
out:
243
	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
244
		printk( "Compressor \"%s\", prio %d\n", this->name, this->priority);
245
	})
246

247
	spin_unlock(&jffs2_compressor_list_lock);
248

249
	return 0;
250
}
251

252
int jffs2_unregister_compressor(struct jffs2_compressor *comp) {
253
	D2(struct jffs2_compressor *this;)
254

255
	D1(printk( "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
256

257
	spin_lock(&jffs2_compressor_list_lock);
258

259
	if (comp->usecount) {
260
		spin_unlock(&jffs2_compressor_list_lock);
261
		printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
262
		return -1;
263
	}
264
	list_del(&comp->list);
265

266
	D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
267
		printk( "Compressor \"%s\", prio %d\n", this->name, this->priority);
268
	})
269
	spin_unlock(&jffs2_compressor_list_lock);
270
	return 0;
271
}
272

273
#ifdef CONFIG_JFFS2_PROC
274

275
#define JFFS2_STAT_BUF_SIZE 16000
276

277
char *jffs2_list_compressors(void) {
278
	struct jffs2_compressor *this;
279
	char *buf, *act_buf;
280

281
	act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
282
	list_for_each_entry(this, &jffs2_compressor_list, list) {
283
		act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority);
284
		if ((this->disabled)||(!this->compress)) {
285
			act_buf += sprintf(act_buf,"disabled");
286
		} else {
287
			act_buf += sprintf(act_buf,"enabled");
288
		}
289
		act_buf += sprintf(act_buf,"\n");
290
	}
291
	return buf;
292
}
293

294
char *jffs2_stats(void) {
295
	struct jffs2_compressor *this;
296
	char *buf, *act_buf;
297

298
	act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
299

300
	act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n");
301
	act_buf += sprintf(act_buf,"%10s   ","none");
302
	act_buf += sprintf(act_buf,"compr: %d blocks (%d)  decompr: %d blocks\n", none_stat_compr_blocks,
303
	none_stat_compr_size, none_stat_decompr_blocks);
304
	spin_lock(&jffs2_compressor_list_lock);
305
	list_for_each_entry(this, &jffs2_compressor_list, list) {
306
		act_buf += sprintf(act_buf,"%10s ",this->name);
307
		if ((this->disabled)||(!this->compress)) {
308
			act_buf += sprintf(act_buf,"- ");
309
		} else {
310
			act_buf += sprintf(act_buf,"+ ");
311
		}
312
		act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d)  decompr: %d blocks ", this->stat_compr_blocks,
313
		this->stat_compr_new_size, this->stat_compr_orig_size,
314
		this->stat_decompr_blocks);
315
		act_buf += sprintf(act_buf,"\n");
316
	}
317
	spin_unlock(&jffs2_compressor_list_lock);
318

319
	return buf;
320
}
321

322
char *jffs2_get_compression_mode_name(void) {
323
	switch (jffs2_compression_mode) {
324
	case JFFS2_COMPR_MODE_NONE:
325
		return "none";
326
	case JFFS2_COMPR_MODE_PRIORITY:
327
		return "priority";
328
	case JFFS2_COMPR_MODE_SIZE:
329
		return "size";
330
	}
331
	return "unkown";
332
}
333

334
int jffs2_set_compression_mode_name(const char *name) {
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
	struct jffs2_compressor *this;
352
	spin_lock(&jffs2_compressor_list_lock);
353
	list_for_each_entry(this, &jffs2_compressor_list, list) {
354
		if (!strcmp(this->name, name)) {
355
			this->disabled = disabled;
356
			spin_unlock(&jffs2_compressor_list_lock);
357
			return 0;
358
		}
359
	}
360
	spin_unlock(&jffs2_compressor_list_lock);
361
	printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
362
	return 1;
363
}
364

365
int jffs2_enable_compressor_name(const char *name) {
366
	return jffs2_compressor_Xable(name, 0);
367
}
368

369
int jffs2_disable_compressor_name(const char *name) {
370
	return jffs2_compressor_Xable(name, 1);
371
}
372

373
int jffs2_set_compressor_priority(const char *name, int priority) {
374
	struct jffs2_compressor *this,*comp;
375
	spin_lock(&jffs2_compressor_list_lock);
376
	list_for_each_entry(this, &jffs2_compressor_list, list) {
377
		if (!strcmp(this->name, name)) {
378
			this->priority = priority;
379
			comp = this;
380
			goto reinsert;
381
		}
382
	}
383
	spin_unlock(&jffs2_compressor_list_lock);
384
	printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
385
	return 1;
386
reinsert:
387
	/* list is sorted in the order of priority, so if
388
	 * we change it we have to reinsert it into the
389
	 * good place
390
	 */
391
	list_del(&comp->list);
392
	list_for_each_entry(this, &jffs2_compressor_list, list) {
393
		if (this->priority < comp->priority) {
394
			list_add(&comp->list, this->list.prev);
395
			spin_unlock(&jffs2_compressor_list_lock);
396
			return 0;
397
		}
398
	}
399
	list_add_tail(&comp->list, &jffs2_compressor_list);
400
	spin_unlock(&jffs2_compressor_list_lock);
401
	return 0;
402
}
403

404
#endif
405

406
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) {
407
	if (orig != comprbuf) {
408
		kfree(comprbuf);
409
	}
410
}
411

412
int jffs2_compressors_init(void) {
413
/* Registering compressors */
414
#ifdef CONFIG_JFFS2_ZLIB
415
        jffs2_zlib_init();
416
#endif
417
#ifdef CONFIG_JFFS2_RTIME
418
        jffs2_rtime_init();
419
#endif
420
#ifdef CONFIG_JFFS2_RUBIN
421
        jffs2_rubinmips_init();
422
        jffs2_dynrubin_init();
423
#endif
424
/* Setting default compression mode */
425
#ifdef CONFIG_JFFS2_CMODE_NONE
426
        jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
427
        D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
428
#else
429
#ifdef CONFIG_JFFS2_CMODE_SIZE
430
        jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
431
        D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
432
#else
433
        D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
434
#endif
435
#endif
436
        return 0;
437
}
438

439
int jffs2_compressors_exit(void)
440
{
441
/* Unregistering compressors */
442
#ifdef CONFIG_JFFS2_RUBIN
443
        jffs2_dynrubin_exit();
444
        jffs2_rubinmips_exit();
445
#endif
446
#ifdef CONFIG_JFFS2_RTIME
447
        jffs2_rtime_exit();
448
#endif
449
#ifdef CONFIG_JFFS2_ZLIB
450
        jffs2_zlib_exit();
451
#endif
452
        return 0;
453
}
454

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.