2019-06-04 11:11:32 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2013-11-18 06:31:36 +04:00
/*
* Copyright ( c ) 2013
* Phillip Lougher < phillip @ squashfs . org . uk >
*/
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/percpu.h>
# include <linux/buffer_head.h>
# include "squashfs_fs.h"
# include "squashfs_fs_sb.h"
# include "decompressor.h"
# include "squashfs.h"
/*
* This file implements multi - threaded decompression using percpu
* variables , one thread per cpu core .
*/
struct squashfs_stream {
void * stream ;
} ;
void * squashfs_decompressor_create ( struct squashfs_sb_info * msblk ,
void * comp_opts )
{
struct squashfs_stream * stream ;
struct squashfs_stream __percpu * percpu ;
int err , cpu ;
percpu = alloc_percpu ( struct squashfs_stream ) ;
if ( percpu = = NULL )
return ERR_PTR ( - ENOMEM ) ;
for_each_possible_cpu ( cpu ) {
stream = per_cpu_ptr ( percpu , cpu ) ;
stream - > stream = msblk - > decompressor - > init ( msblk , comp_opts ) ;
if ( IS_ERR ( stream - > stream ) ) {
err = PTR_ERR ( stream - > stream ) ;
goto out ;
}
}
kfree ( comp_opts ) ;
return ( __force void * ) percpu ;
out :
for_each_possible_cpu ( cpu ) {
stream = per_cpu_ptr ( percpu , cpu ) ;
if ( ! IS_ERR_OR_NULL ( stream - > stream ) )
msblk - > decompressor - > free ( stream - > stream ) ;
}
free_percpu ( percpu ) ;
return ERR_PTR ( err ) ;
}
void squashfs_decompressor_destroy ( struct squashfs_sb_info * msblk )
{
struct squashfs_stream __percpu * percpu =
( struct squashfs_stream __percpu * ) msblk - > stream ;
struct squashfs_stream * stream ;
int cpu ;
if ( msblk - > stream ) {
for_each_possible_cpu ( cpu ) {
stream = per_cpu_ptr ( percpu , cpu ) ;
msblk - > decompressor - > free ( stream - > stream ) ;
}
free_percpu ( percpu ) ;
}
}
2013-11-18 06:59:12 +04:00
int squashfs_decompress ( struct squashfs_sb_info * msblk , struct buffer_head * * bh ,
int b , int offset , int length , struct squashfs_page_actor * output )
2013-11-18 06:31:36 +04:00
{
struct squashfs_stream __percpu * percpu =
( struct squashfs_stream __percpu * ) msblk - > stream ;
struct squashfs_stream * stream = get_cpu_ptr ( percpu ) ;
2013-11-18 06:59:12 +04:00
int res = msblk - > decompressor - > decompress ( msblk , stream - > stream , bh , b ,
offset , length , output ) ;
2013-11-18 06:31:36 +04:00
put_cpu_ptr ( stream ) ;
if ( res < 0 )
ERROR ( " %s decompression failed, data probably corrupt \n " ,
msblk - > decompressor - > name ) ;
return res ;
}
int squashfs_max_decompressors ( void )
{
return num_possible_cpus ( ) ;
}