mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	jffs2: add compr=lzo and compr=zlib options
..to allow forcing of either compression scheme. This will override compiled-in defaults. jffs2_compress is reworked a bit, as the lzo/zlib override shares lots of code w/ the PRIORITY mode. v2: update show_options accordingly. Signed-off-by: Andres Salomon <dilinger@queued.net> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
This commit is contained in:
		
							parent
							
								
									92abc475d8
								
							
						
					
					
						commit
						123005f3cc
					
				
					 3 changed files with 110 additions and 37 deletions
				
			
		
							
								
								
									
										119
									
								
								fs/jffs2/compr.c
									
										
									
									
									
								
							
							
						
						
									
										119
									
								
								fs/jffs2/compr.c
									
										
									
									
									
								
							|  | @ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * jffs2_selected_compress: | ||||
|  * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB). | ||||
|  *	If 0, just take the first available compression mode. | ||||
|  * @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: the compression type used.  Zero is used to show that the data | ||||
|  * could not be compressed; probably because we couldn't find the requested | ||||
|  * compression mode. | ||||
|  */ | ||||
| static int jffs2_selected_compress(u8 compr, unsigned char *data_in, | ||||
| 		unsigned char **cpage_out, u32 *datalen, u32 *cdatalen) | ||||
| { | ||||
| 	struct jffs2_compressor *this; | ||||
| 	int err, ret = JFFS2_COMPR_NONE; | ||||
| 	uint32_t orig_slen, orig_dlen; | ||||
| 	char *output_buf; | ||||
| 
 | ||||
| 	output_buf = kmalloc(*cdatalen, GFP_KERNEL); | ||||
| 	if (!output_buf) { | ||||
| 		printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	orig_slen = *datalen; | ||||
| 	orig_dlen = *cdatalen; | ||||
| 	spin_lock(&jffs2_compressor_list_lock); | ||||
| 	list_for_each_entry(this, &jffs2_compressor_list, list) { | ||||
| 		/* Skip decompress-only and disabled modules */ | ||||
| 		if (!this->compress || this->disabled) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* Skip if not the desired compression type */ | ||||
| 		if (compr && (compr != this->compr)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Either compression type was unspecified, or we found our | ||||
| 		 * compressor; either way, we're good to go. | ||||
| 		 */ | ||||
| 		this->usecount++; | ||||
| 		spin_unlock(&jffs2_compressor_list_lock); | ||||
| 
 | ||||
| 		*datalen  = orig_slen; | ||||
| 		*cdatalen = orig_dlen; | ||||
| 		err = this->compress(data_in, output_buf, datalen, cdatalen); | ||||
| 
 | ||||
| 		spin_lock(&jffs2_compressor_list_lock); | ||||
| 		this->usecount--; | ||||
| 		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 | ||||
|  | @ -91,37 +163,8 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
| 	case JFFS2_COMPR_MODE_NONE: | ||||
| 		break; | ||||
| 	case JFFS2_COMPR_MODE_PRIORITY: | ||||
| 		output_buf = kmalloc(*cdatalen,GFP_KERNEL); | ||||
| 		if (!output_buf) { | ||||
| 			printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		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; | ||||
| 
 | ||||
| 			this->usecount++; | ||||
| 			spin_unlock(&jffs2_compressor_list_lock); | ||||
| 			*datalen  = orig_slen; | ||||
| 			*cdatalen = orig_dlen; | ||||
| 			compr_ret = this->compress(data_in, output_buf, datalen, cdatalen); | ||||
| 			spin_lock(&jffs2_compressor_list_lock); | ||||
| 			this->usecount--; | ||||
| 			if (!compr_ret) { | ||||
| 				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); | ||||
| 		ret = jffs2_selected_compress(0, data_in, cpage_out, datalen, | ||||
| 				cdatalen); | ||||
| 		break; | ||||
| 	case JFFS2_COMPR_MODE_SIZE: | ||||
| 	case JFFS2_COMPR_MODE_FAVOURLZO: | ||||
|  | @ -179,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
| 			best->stat_compr_orig_size += best_slen; | ||||
| 			best->stat_compr_new_size  += best_dlen; | ||||
| 			ret = best->compr; | ||||
| 			*cpage_out = output_buf; | ||||
| 		} | ||||
| 		spin_unlock(&jffs2_compressor_list_lock); | ||||
| 		break; | ||||
| 	case JFFS2_COMPR_MODE_FORCELZO: | ||||
| 		ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in, | ||||
| 				cpage_out, datalen, cdatalen); | ||||
| 		break; | ||||
| 	case JFFS2_COMPR_MODE_FORCEZLIB: | ||||
| 		ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in, | ||||
| 				cpage_out, datalen, cdatalen); | ||||
| 		break; | ||||
| 	default: | ||||
| 		printk(KERN_ERR "JFFS2: unknown compression mode.\n"); | ||||
| 	} | ||||
|  out: | ||||
| 
 | ||||
| 	if (ret == JFFS2_COMPR_NONE) { | ||||
| 		*cpage_out = data_in; | ||||
| 		*datalen = *cdatalen; | ||||
| 		none_stat_compr_blocks++; | ||||
| 		none_stat_compr_size += *datalen; | ||||
| 	} | ||||
| 	else { | ||||
| 		*cpage_out = output_buf; | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,6 +40,8 @@ | |||
| #define JFFS2_COMPR_MODE_PRIORITY   1 | ||||
| #define JFFS2_COMPR_MODE_SIZE       2 | ||||
| #define JFFS2_COMPR_MODE_FAVOURLZO  3 | ||||
| #define JFFS2_COMPR_MODE_FORCELZO   4 | ||||
| #define JFFS2_COMPR_MODE_FORCEZLIB  5 | ||||
| 
 | ||||
| #define FAVOUR_LZO_PERCENT 80 | ||||
| 
 | ||||
|  |  | |||
|  | @ -82,6 +82,14 @@ static const char *jffs2_compr_name(unsigned int compr) | |||
| 	switch (compr) { | ||||
| 	case JFFS2_COMPR_MODE_NONE: | ||||
| 		return "none"; | ||||
| #ifdef CONFIG_JFFS2_LZO | ||||
| 	case JFFS2_COMPR_MODE_FORCELZO: | ||||
| 		return "lzo"; | ||||
| #endif | ||||
| #ifdef CONFIG_JFFS2_ZLIB | ||||
| 	case JFFS2_COMPR_MODE_FORCEZLIB: | ||||
| 		return "zlib"; | ||||
| #endif | ||||
| 	default: | ||||
| 		/* should never happen; programmer error */ | ||||
| 		WARN_ON(1); | ||||
|  | @ -195,11 +203,25 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) | |||
| 
 | ||||
| 			if (!name) | ||||
| 				return -ENOMEM; | ||||
| 			if (!strcmp(name, "none")) { | ||||
| 			if (!strcmp(name, "none")) | ||||
| 				c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; | ||||
| 				c->mount_opts.override_compr = true; | ||||
| #ifdef CONFIG_JFFS2_LZO | ||||
| 			else if (!strcmp(name, "lzo")) | ||||
| 				c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO; | ||||
| #endif | ||||
| #ifdef CONFIG_JFFS2_ZLIB | ||||
| 			else if (!strcmp(name, "zlib")) | ||||
| 				c->mount_opts.compr = | ||||
| 						JFFS2_COMPR_MODE_FORCEZLIB; | ||||
| #endif | ||||
| 			else { | ||||
| 				printk(KERN_ERR "JFFS2 Error: unknown compressor \"%s\"", | ||||
| 						name); | ||||
| 				kfree(name); | ||||
| 				return -EINVAL; | ||||
| 			} | ||||
| 			kfree(name); | ||||
| 			c->mount_opts.override_compr = true; | ||||
| 			break; | ||||
| 		default: | ||||
| 			printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n", | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Andres Salomon
						Andres Salomon