2019-07-31 18:57:31 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
/*
2018-07-26 15:21:57 +03:00
* Copyright ( C ) 2018 HUAWEI , Inc .
2020-07-13 16:09:44 +03:00
* https : //www.huawei.com/
2018-07-26 15:21:57 +03:00
*/
2019-07-31 18:57:32 +03:00
# ifndef __EROFS_FS_ZPVEC_H
# define __EROFS_FS_ZPVEC_H
2018-07-26 15:21:57 +03:00
2019-07-31 18:57:32 +03:00
# include "tagptr.h"
2018-07-26 15:21:57 +03:00
2019-07-31 18:57:45 +03:00
/* page type in pagevec for decompress subsystem */
2018-07-26 15:21:57 +03:00
enum z_erofs_page_type {
/* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */
Z_EROFS_PAGE_TYPE_EXCLUSIVE ,
Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED ,
Z_EROFS_VLE_PAGE_TYPE_HEAD ,
Z_EROFS_VLE_PAGE_TYPE_MAX
} ;
extern void __compiletime_error ( " Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0 " )
__bad_page_type_exclusive ( void ) ;
/* pagevec tagged pointer */
typedef tagptr2_t erofs_vtptr_t ;
/* pagevec collector */
struct z_erofs_pagevec_ctor {
struct page * curr , * next ;
erofs_vtptr_t * pages ;
unsigned int nr , index ;
} ;
static inline void z_erofs_pagevec_ctor_exit ( struct z_erofs_pagevec_ctor * ctor ,
bool atomic )
{
2019-03-22 05:38:16 +03:00
if ( ! ctor - > curr )
2018-07-26 15:21:57 +03:00
return ;
if ( atomic )
kunmap_atomic ( ctor - > pages ) ;
else
kunmap ( ctor - > curr ) ;
}
static inline struct page *
z_erofs_pagevec_ctor_next_page ( struct z_erofs_pagevec_ctor * ctor ,
2019-07-15 15:21:27 +03:00
unsigned int nr )
2018-07-26 15:21:57 +03:00
{
2019-07-15 15:21:27 +03:00
unsigned int index ;
2018-07-26 15:21:57 +03:00
/* keep away from occupied pages */
2019-03-22 05:38:16 +03:00
if ( ctor - > next )
2018-07-26 15:21:57 +03:00
return ctor - > next ;
for ( index = 0 ; index < nr ; + + index ) {
const erofs_vtptr_t t = ctor - > pages [ index ] ;
2019-07-15 15:21:27 +03:00
const unsigned int tags = tagptr_unfold_tags ( t ) ;
2018-07-26 15:21:57 +03:00
if ( tags = = Z_EROFS_PAGE_TYPE_EXCLUSIVE )
return tagptr_unfold_ptr ( t ) ;
}
2019-05-19 12:35:57 +03:00
DBG_BUGON ( nr > = ctor - > nr ) ;
2018-07-26 15:21:57 +03:00
return NULL ;
}
static inline void
z_erofs_pagevec_ctor_pagedown ( struct z_erofs_pagevec_ctor * ctor ,
bool atomic )
{
struct page * next = z_erofs_pagevec_ctor_next_page ( ctor , ctor - > nr ) ;
z_erofs_pagevec_ctor_exit ( ctor , atomic ) ;
ctor - > curr = next ;
ctor - > next = NULL ;
ctor - > pages = atomic ?
kmap_atomic ( ctor - > curr ) : kmap ( ctor - > curr ) ;
ctor - > nr = PAGE_SIZE / sizeof ( struct page * ) ;
ctor - > index = 0 ;
}
static inline void z_erofs_pagevec_ctor_init ( struct z_erofs_pagevec_ctor * ctor ,
2019-07-15 15:21:27 +03:00
unsigned int nr ,
erofs_vtptr_t * pages ,
unsigned int i )
2018-07-26 15:21:57 +03:00
{
ctor - > nr = nr ;
ctor - > curr = ctor - > next = NULL ;
ctor - > pages = pages ;
if ( i > = nr ) {
i - = nr ;
z_erofs_pagevec_ctor_pagedown ( ctor , false ) ;
while ( i > ctor - > nr ) {
i - = ctor - > nr ;
z_erofs_pagevec_ctor_pagedown ( ctor , false ) ;
}
}
ctor - > next = z_erofs_pagevec_ctor_next_page ( ctor , i ) ;
ctor - > index = i ;
}
2019-07-31 18:57:45 +03:00
static inline bool z_erofs_pagevec_enqueue ( struct z_erofs_pagevec_ctor * ctor ,
struct page * page ,
2021-04-19 13:26:23 +03:00
enum z_erofs_page_type type )
2018-07-26 15:21:57 +03:00
{
2019-08-29 19:38:27 +03:00
if ( ! ctor - > next & & type )
2018-07-26 15:21:57 +03:00
if ( ctor - > index + 1 = = ctor - > nr )
return false ;
2019-08-29 19:38:27 +03:00
if ( ctor - > index > = ctor - > nr )
2018-07-26 15:21:57 +03:00
z_erofs_pagevec_ctor_pagedown ( ctor , false ) ;
/* exclusive page type must be 0 */
if ( Z_EROFS_PAGE_TYPE_EXCLUSIVE ! = ( uintptr_t ) NULL )
__bad_page_type_exclusive ( ) ;
/* should remind that collector->next never equal to 1, 2 */
if ( type = = ( uintptr_t ) ctor - > next ) {
ctor - > next = page ;
}
2019-07-31 18:57:45 +03:00
ctor - > pages [ ctor - > index + + ] = tagptr_fold ( erofs_vtptr_t , page , type ) ;
2018-07-26 15:21:57 +03:00
return true ;
}
static inline struct page *
2019-07-31 18:57:45 +03:00
z_erofs_pagevec_dequeue ( struct z_erofs_pagevec_ctor * ctor ,
enum z_erofs_page_type * type )
2018-07-26 15:21:57 +03:00
{
erofs_vtptr_t t ;
2019-08-29 19:38:27 +03:00
if ( ctor - > index > = ctor - > nr ) {
2018-12-11 10:17:49 +03:00
DBG_BUGON ( ! ctor - > next ) ;
2018-07-26 15:21:57 +03:00
z_erofs_pagevec_ctor_pagedown ( ctor , true ) ;
}
t = ctor - > pages [ ctor - > index ] ;
* type = tagptr_unfold_tags ( t ) ;
/* should remind that collector->next never equal to 1, 2 */
if ( * type = = ( uintptr_t ) ctor - > next )
ctor - > next = tagptr_unfold_ptr ( t ) ;
2019-07-31 18:57:45 +03:00
ctor - > pages [ ctor - > index + + ] = tagptr_fold ( erofs_vtptr_t , NULL , 0 ) ;
2018-07-26 15:21:57 +03:00
return tagptr_unfold_ptr ( t ) ;
}
# endif