fs/jffs2/compr.c

Source file repositories/reference/linux-study-clean/fs/jffs2/compr.c

File Facts

System
Linux kernel
Corpus path
fs/jffs2/compr.c
Extension
.c
Size
12020 bytes
Lines
427
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!err) {
			/* Success */
			ret = this->compr;
			this->stat_compr_blocks++;
			this->stat_compr_orig_size += *datalen;
			this->stat_compr_new_size += *cdatalen;
			break;
		}
	}
	spin_unlock(&jffs2_compressor_list_lock);
	if (ret == JFFS2_COMPR_NONE)
		kfree(output_buf);
	else
		*cpage_out = output_buf;

	return ret;
}

/* jffs2_compress:
 * @data_in: Pointer to uncompressed data
 * @cpage_out: Pointer to returned pointer to buffer for compressed data
 * @datalen: On entry, holds the amount of data available for compression.
 *	On exit, expected to hold the amount of data actually compressed.
 * @cdatalen: On entry, holds the amount of space available for compressed
 *	data. On exit, expected to hold the actual size of the compressed
 *	data.
 *
 * Returns: Lower byte to be stored with data indicating compression type used.
 * Zero is used to show that the data could not be compressed - the
 * compressed version was actually larger than the original.
 * Upper byte will be used later. (soon)
 *
 * If the cdata buffer isn't large enough to hold all the uncompressed data,
 * jffs2_compress should compress as much as will fit, and should set
 * *datalen accordingly to show the amount of data which were compressed.
 */
uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
			unsigned char *data_in, unsigned char **cpage_out,
			uint32_t *datalen, uint32_t *cdatalen)
{
	int ret = JFFS2_COMPR_NONE;
	int mode, compr_ret;
	struct jffs2_compressor *this, *best=NULL;
	unsigned char *output_buf = NULL, *tmp_buf;
	uint32_t orig_slen, orig_dlen;
	uint32_t best_slen=0, best_dlen=0;

	if (c->mount_opts.override_compr)
		mode = c->mount_opts.compr;
	else
		mode = jffs2_compression_mode;

	switch (mode) {
	case JFFS2_COMPR_MODE_NONE:
		break;
	case JFFS2_COMPR_MODE_PRIORITY:
		ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
				cdatalen);
		break;
	case JFFS2_COMPR_MODE_SIZE:
	case JFFS2_COMPR_MODE_FAVOURLZO:
		orig_slen = *datalen;
		orig_dlen = *cdatalen;
		spin_lock(&jffs2_compressor_list_lock);
		list_for_each_entry(this, &jffs2_compressor_list, list) {
			/* Skip decompress-only backwards-compatibility and disabled modules */
			if ((!this->compress)||(this->disabled))
				continue;
			/* Allocating memory for output buffer if necessary */
			if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
				spin_unlock(&jffs2_compressor_list_lock);
				kfree(this->compr_buf);
				spin_lock(&jffs2_compressor_list_lock);
				this->compr_buf_size=0;
				this->compr_buf=NULL;
			}
			if (!this->compr_buf) {
				spin_unlock(&jffs2_compressor_list_lock);
				tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
				spin_lock(&jffs2_compressor_list_lock);
				if (!tmp_buf) {
					pr_warn("No memory for compressor allocation. (%d bytes)\n",
						orig_slen);
					continue;
				}
				else {
					this->compr_buf = tmp_buf;
					this->compr_buf_size = orig_slen;
				}
			}

Annotation

Implementation Notes