2017-12-18 06:00:59 +03:00
// SPDX-License-Identifier: GPL-2.0
2012-11-09 00:18:54 +04:00
/*
* fs / ext4 / extents_status . h
*
* Written by Yongqiang Yang < xiaoqiangnk @ gmail . com >
* Modified by
* Allison Henderson < achender @ linux . vnet . ibm . com >
* Zheng Liu < wenqing . lz @ taobao . com >
*
*/
# ifndef _EXT4_EXTENTS_STATUS_H
# define _EXT4_EXTENTS_STATUS_H
2012-11-09 06:57:20 +04:00
/*
* Turn on ES_DEBUG__ to get lots of info about extent status operations .
*/
# ifdef ES_DEBUG__
# define es_debug(fmt, ...) printk(fmt, ##__VA_ARGS__)
# else
# define es_debug(fmt, ...) no_printk(fmt, ##__VA_ARGS__)
# endif
2013-03-11 05:01:03 +04:00
/*
* With ES_AGGRESSIVE_TEST defined , the result of es caching will be
* checked with old map_block ' s result .
*/
# define ES_AGGRESSIVE_TEST__
2013-02-27 23:54:37 +04:00
/*
* These flags live in the high bits of extent_status . es_pblk
*/
2014-11-25 19:53:47 +03:00
enum {
ES_WRITTEN_B ,
ES_UNWRITTEN_B ,
ES_DELAYED_B ,
ES_HOLE_B ,
2014-11-25 19:55:24 +03:00
ES_REFERENCED_B ,
2014-11-25 19:53:47 +03:00
ES_FLAGS
} ;
2013-02-18 09:26:51 +04:00
2014-11-25 19:53:47 +03:00
# define ES_SHIFT (sizeof(ext4_fsblk_t)*8 - ES_FLAGS)
# define ES_MASK (~((ext4_fsblk_t)0) << ES_SHIFT)
2013-08-17 05:22:41 +04:00
2014-11-25 19:53:47 +03:00
# define EXTENT_STATUS_WRITTEN (1 << ES_WRITTEN_B)
# define EXTENT_STATUS_UNWRITTEN (1 << ES_UNWRITTEN_B)
# define EXTENT_STATUS_DELAYED (1 << ES_DELAYED_B)
# define EXTENT_STATUS_HOLE (1 << ES_HOLE_B)
2014-11-25 19:55:24 +03:00
# define EXTENT_STATUS_REFERENCED (1 << ES_REFERENCED_B)
# define ES_TYPE_MASK ((ext4_fsblk_t)(EXTENT_STATUS_WRITTEN | \
EXTENT_STATUS_UNWRITTEN | \
EXTENT_STATUS_DELAYED | \
EXTENT_STATUS_HOLE ) < < ES_SHIFT )
2013-08-17 05:22:41 +04:00
2013-07-01 16:12:37 +04:00
struct ext4_sb_info ;
2013-03-11 05:13:05 +04:00
struct ext4_extent ;
2012-11-09 00:18:54 +04:00
struct extent_status {
struct rb_node rb_node ;
2013-02-18 09:26:51 +04:00
ext4_lblk_t es_lblk ; /* first logical block extent covers */
ext4_lblk_t es_len ; /* length of extent in block */
2013-02-18 09:26:51 +04:00
ext4_fsblk_t es_pblk ; /* first physical block */
2012-11-09 00:18:54 +04:00
} ;
struct ext4_es_tree {
struct rb_root root ;
struct extent_status * cache_es ; /* recently accessed extent */
} ;
2014-09-02 06:26:49 +04:00
struct ext4_es_stats {
unsigned long es_stats_shrunk ;
unsigned long es_stats_cache_hits ;
unsigned long es_stats_cache_misses ;
u64 es_stats_scan_time ;
u64 es_stats_max_scan_time ;
struct percpu_counter es_stats_all_cnt ;
2014-11-25 19:45:37 +03:00
struct percpu_counter es_stats_shk_cnt ;
2014-09-02 06:26:49 +04:00
} ;
2012-11-09 06:57:20 +04:00
extern int __init ext4_init_es ( void ) ;
extern void ext4_exit_es ( void ) ;
extern void ext4_es_init_tree ( struct ext4_es_tree * tree ) ;
2013-02-18 09:26:51 +04:00
extern int ext4_es_insert_extent ( struct inode * inode , ext4_lblk_t lblk ,
2013-02-18 09:26:51 +04:00
ext4_lblk_t len , ext4_fsblk_t pblk ,
2013-08-17 05:22:41 +04:00
unsigned int status ) ;
2013-08-17 05:23:41 +04:00
extern void ext4_es_cache_extent ( struct inode * inode , ext4_lblk_t lblk ,
ext4_lblk_t len , ext4_fsblk_t pblk ,
unsigned int status ) ;
2013-02-18 09:26:51 +04:00
extern int ext4_es_remove_extent ( struct inode * inode , ext4_lblk_t lblk ,
2012-11-09 06:57:20 +04:00
ext4_lblk_t len ) ;
2018-10-01 21:10:39 +03:00
extern void ext4_es_find_extent_range ( struct inode * inode ,
int ( * match_fn ) ( struct extent_status * es ) ,
ext4_lblk_t lblk , ext4_lblk_t end ,
struct extent_status * es ) ;
2013-02-18 09:29:59 +04:00
extern int ext4_es_lookup_extent ( struct inode * inode , ext4_lblk_t lblk ,
struct extent_status * es ) ;
2018-10-01 21:10:39 +03:00
extern bool ext4_es_scan_range ( struct inode * inode ,
int ( * matching_fn ) ( struct extent_status * es ) ,
ext4_lblk_t lblk , ext4_lblk_t end ) ;
extern bool ext4_es_scan_clu ( struct inode * inode ,
int ( * matching_fn ) ( struct extent_status * es ) ,
ext4_lblk_t lblk ) ;
2012-11-09 06:57:20 +04:00
2014-11-25 19:53:47 +03:00
static inline unsigned int ext4_es_status ( struct extent_status * es )
{
return es - > es_pblk > > ES_SHIFT ;
}
2014-11-25 19:55:24 +03:00
static inline unsigned int ext4_es_type ( struct extent_status * es )
{
return ( es - > es_pblk & ES_TYPE_MASK ) > > ES_SHIFT ;
}
2013-02-18 09:26:51 +04:00
static inline int ext4_es_is_written ( struct extent_status * es )
{
2014-11-25 19:55:24 +03:00
return ( ext4_es_type ( es ) & EXTENT_STATUS_WRITTEN ) ! = 0 ;
2013-02-18 09:26:51 +04:00
}
static inline int ext4_es_is_unwritten ( struct extent_status * es )
{
2014-11-25 19:55:24 +03:00
return ( ext4_es_type ( es ) & EXTENT_STATUS_UNWRITTEN ) ! = 0 ;
2013-02-18 09:26:51 +04:00
}
static inline int ext4_es_is_delayed ( struct extent_status * es )
{
2014-11-25 19:55:24 +03:00
return ( ext4_es_type ( es ) & EXTENT_STATUS_DELAYED ) ! = 0 ;
2013-02-18 09:26:51 +04:00
}
static inline int ext4_es_is_hole ( struct extent_status * es )
{
2014-11-25 19:55:24 +03:00
return ( ext4_es_type ( es ) & EXTENT_STATUS_HOLE ) ! = 0 ;
}
static inline void ext4_es_set_referenced ( struct extent_status * es )
{
es - > es_pblk | = ( ( ext4_fsblk_t ) EXTENT_STATUS_REFERENCED ) < < ES_SHIFT ;
}
static inline void ext4_es_clear_referenced ( struct extent_status * es )
{
es - > es_pblk & = ~ ( ( ( ext4_fsblk_t ) EXTENT_STATUS_REFERENCED ) < < ES_SHIFT ) ;
}
static inline int ext4_es_is_referenced ( struct extent_status * es )
{
return ( ext4_es_status ( es ) & EXTENT_STATUS_REFERENCED ) ! = 0 ;
2013-02-18 09:26:51 +04:00
}
static inline ext4_fsblk_t ext4_es_pblock ( struct extent_status * es )
{
2013-08-17 05:22:41 +04:00
return es - > es_pblk & ~ ES_MASK ;
2013-02-18 09:26:51 +04:00
}
static inline void ext4_es_store_pblock ( struct extent_status * es ,
ext4_fsblk_t pb )
{
ext4_fsblk_t block ;
2013-08-17 05:22:41 +04:00
block = ( pb & ~ ES_MASK ) | ( es - > es_pblk & ES_MASK ) ;
2013-02-18 09:26:51 +04:00
es - > es_pblk = block ;
}
static inline void ext4_es_store_status ( struct extent_status * es ,
2013-08-17 05:22:41 +04:00
unsigned int status )
2013-02-18 09:26:51 +04:00
{
2014-11-25 19:53:47 +03:00
es - > es_pblk = ( ( ( ext4_fsblk_t ) status < < ES_SHIFT ) & ES_MASK ) |
( es - > es_pblk & ~ ES_MASK ) ;
2013-02-18 09:26:51 +04:00
}
2014-02-20 05:15:15 +04:00
static inline void ext4_es_store_pblock_status ( struct extent_status * es ,
ext4_fsblk_t pb ,
unsigned int status )
{
2014-11-25 19:53:47 +03:00
es - > es_pblk = ( ( ( ext4_fsblk_t ) status < < ES_SHIFT ) & ES_MASK ) |
( pb & ~ ES_MASK ) ;
2014-02-20 05:15:15 +04:00
}
2014-09-02 06:26:49 +04:00
extern int ext4_es_register_shrinker ( struct ext4_sb_info * sbi ) ;
2013-07-01 16:12:37 +04:00
extern void ext4_es_unregister_shrinker ( struct ext4_sb_info * sbi ) ;
2013-02-18 09:32:55 +04:00
2015-09-23 19:46:17 +03:00
extern int ext4_seq_es_shrinker_info_show ( struct seq_file * seq , void * v ) ;
2012-11-09 00:18:54 +04:00
# endif /* _EXT4_EXTENTS_STATUS_H */