LCOV - code coverage report
Current view: top level - fs/ext4 - extents_status.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 15 19 78.9 %
Date: 2020-09-30 20:25:40 Functions: 1 3 33.3 %
Branches: 4 24 16.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  *  fs/ext4/extents_status.h
       4                 :            :  *
       5                 :            :  * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
       6                 :            :  * Modified by
       7                 :            :  *      Allison Henderson <achender@linux.vnet.ibm.com>
       8                 :            :  *      Zheng Liu <wenqing.lz@taobao.com>
       9                 :            :  *
      10                 :            :  */
      11                 :            : 
      12                 :            : #ifndef _EXT4_EXTENTS_STATUS_H
      13                 :            : #define _EXT4_EXTENTS_STATUS_H
      14                 :            : 
      15                 :            : /*
      16                 :            :  * Turn on ES_DEBUG__ to get lots of info about extent status operations.
      17                 :            :  */
      18                 :            : #ifdef ES_DEBUG__
      19                 :            : #define es_debug(fmt, ...)      printk(fmt, ##__VA_ARGS__)
      20                 :            : #else
      21                 :            : #define es_debug(fmt, ...)      no_printk(fmt, ##__VA_ARGS__)
      22                 :            : #endif
      23                 :            : 
      24                 :            : /*
      25                 :            :  * With ES_AGGRESSIVE_TEST defined, the result of es caching will be
      26                 :            :  * checked with old map_block's result.
      27                 :            :  */
      28                 :            : #define ES_AGGRESSIVE_TEST__
      29                 :            : 
      30                 :            : /*
      31                 :            :  * These flags live in the high bits of extent_status.es_pblk
      32                 :            :  */
      33                 :            : enum {
      34                 :            :         ES_WRITTEN_B,
      35                 :            :         ES_UNWRITTEN_B,
      36                 :            :         ES_DELAYED_B,
      37                 :            :         ES_HOLE_B,
      38                 :            :         ES_REFERENCED_B,
      39                 :            :         ES_FLAGS
      40                 :            : };
      41                 :            : 
      42                 :            : #define ES_SHIFT (sizeof(ext4_fsblk_t)*8 - ES_FLAGS)
      43                 :            : #define ES_MASK (~((ext4_fsblk_t)0) << ES_SHIFT)
      44                 :            : 
      45                 :            : #define EXTENT_STATUS_WRITTEN   (1 << ES_WRITTEN_B)
      46                 :            : #define EXTENT_STATUS_UNWRITTEN (1 << ES_UNWRITTEN_B)
      47                 :            : #define EXTENT_STATUS_DELAYED   (1 << ES_DELAYED_B)
      48                 :            : #define EXTENT_STATUS_HOLE      (1 << ES_HOLE_B)
      49                 :            : #define EXTENT_STATUS_REFERENCED        (1 << ES_REFERENCED_B)
      50                 :            : 
      51                 :            : #define ES_TYPE_MASK    ((ext4_fsblk_t)(EXTENT_STATUS_WRITTEN | \
      52                 :            :                           EXTENT_STATUS_UNWRITTEN | \
      53                 :            :                           EXTENT_STATUS_DELAYED | \
      54                 :            :                           EXTENT_STATUS_HOLE) << ES_SHIFT)
      55                 :            : 
      56                 :            : struct ext4_sb_info;
      57                 :            : struct ext4_extent;
      58                 :            : 
      59                 :            : struct extent_status {
      60                 :            :         struct rb_node rb_node;
      61                 :            :         ext4_lblk_t es_lblk;    /* first logical block extent covers */
      62                 :            :         ext4_lblk_t es_len;     /* length of extent in block */
      63                 :            :         ext4_fsblk_t es_pblk;   /* first physical block */
      64                 :            : };
      65                 :            : 
      66                 :            : struct ext4_es_tree {
      67                 :            :         struct rb_root root;
      68                 :            :         struct extent_status *cache_es; /* recently accessed extent */
      69                 :            : };
      70                 :            : 
      71                 :            : struct ext4_es_stats {
      72                 :            :         unsigned long es_stats_shrunk;
      73                 :            :         struct percpu_counter es_stats_cache_hits;
      74                 :            :         struct percpu_counter es_stats_cache_misses;
      75                 :            :         u64 es_stats_scan_time;
      76                 :            :         u64 es_stats_max_scan_time;
      77                 :            :         struct percpu_counter es_stats_all_cnt;
      78                 :            :         struct percpu_counter es_stats_shk_cnt;
      79                 :            : };
      80                 :            : 
      81                 :            : /*
      82                 :            :  * Pending cluster reservations for bigalloc file systems
      83                 :            :  *
      84                 :            :  * A cluster with a pending reservation is a logical cluster shared by at
      85                 :            :  * least one extent in the extents status tree with delayed and unwritten
      86                 :            :  * status and at least one other written or unwritten extent.  The
      87                 :            :  * reservation is said to be pending because a cluster reservation would
      88                 :            :  * have to be taken in the event all blocks in the cluster shared with
      89                 :            :  * written or unwritten extents were deleted while the delayed and
      90                 :            :  * unwritten blocks remained.
      91                 :            :  *
      92                 :            :  * The set of pending cluster reservations is an auxiliary data structure
      93                 :            :  * used with the extents status tree to implement reserved cluster/block
      94                 :            :  * accounting for bigalloc file systems.  The set is kept in memory and
      95                 :            :  * records all pending cluster reservations.
      96                 :            :  *
      97                 :            :  * Its primary function is to avoid the need to read extents from the
      98                 :            :  * disk when invalidating pages as a result of a truncate, punch hole, or
      99                 :            :  * collapse range operation.  Page invalidation requires a decrease in the
     100                 :            :  * reserved cluster count if it results in the removal of all delayed
     101                 :            :  * and unwritten extents (blocks) from a cluster that is not shared with a
     102                 :            :  * written or unwritten extent, and no decrease otherwise.  Determining
     103                 :            :  * whether the cluster is shared can be done by searching for a pending
     104                 :            :  * reservation on it.
     105                 :            :  *
     106                 :            :  * Secondarily, it provides a potentially faster method for determining
     107                 :            :  * whether the reserved cluster count should be increased when a physical
     108                 :            :  * cluster is deallocated as a result of a truncate, punch hole, or
     109                 :            :  * collapse range operation.  The necessary information is also present
     110                 :            :  * in the extents status tree, but might be more rapidly accessed in
     111                 :            :  * the pending reservation set in many cases due to smaller size.
     112                 :            :  *
     113                 :            :  * The pending cluster reservation set is implemented as a red-black tree
     114                 :            :  * with the goal of minimizing per page search time overhead.
     115                 :            :  */
     116                 :            : 
     117                 :            : struct pending_reservation {
     118                 :            :         struct rb_node rb_node;
     119                 :            :         ext4_lblk_t lclu;
     120                 :            : };
     121                 :            : 
     122                 :            : struct ext4_pending_tree {
     123                 :            :         struct rb_root root;
     124                 :            : };
     125                 :            : 
     126                 :            : extern int __init ext4_init_es(void);
     127                 :            : extern void ext4_exit_es(void);
     128                 :            : extern void ext4_es_init_tree(struct ext4_es_tree *tree);
     129                 :            : 
     130                 :            : extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
     131                 :            :                                  ext4_lblk_t len, ext4_fsblk_t pblk,
     132                 :            :                                  unsigned int status);
     133                 :            : extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
     134                 :            :                                  ext4_lblk_t len, ext4_fsblk_t pblk,
     135                 :            :                                  unsigned int status);
     136                 :            : extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
     137                 :            :                                  ext4_lblk_t len);
     138                 :            : extern void ext4_es_find_extent_range(struct inode *inode,
     139                 :            :                                       int (*match_fn)(struct extent_status *es),
     140                 :            :                                       ext4_lblk_t lblk, ext4_lblk_t end,
     141                 :            :                                       struct extent_status *es);
     142                 :            : extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
     143                 :            :                                  ext4_lblk_t *next_lblk,
     144                 :            :                                  struct extent_status *es);
     145                 :            : extern bool ext4_es_scan_range(struct inode *inode,
     146                 :            :                                int (*matching_fn)(struct extent_status *es),
     147                 :            :                                ext4_lblk_t lblk, ext4_lblk_t end);
     148                 :            : extern bool ext4_es_scan_clu(struct inode *inode,
     149                 :            :                              int (*matching_fn)(struct extent_status *es),
     150                 :            :                              ext4_lblk_t lblk);
     151                 :            : 
     152                 :            : static inline unsigned int ext4_es_status(struct extent_status *es)
     153                 :            : {
     154                 :    7932719 :         return es->es_pblk >> ES_SHIFT;
     155                 :            : }
     156                 :            : 
     157                 :            : static inline unsigned int ext4_es_type(struct extent_status *es)
     158                 :            : {
     159                 :   11040140 :         return (es->es_pblk & ES_TYPE_MASK) >> ES_SHIFT;
     160                 :            : }
     161                 :            : 
     162                 :            : static inline int ext4_es_is_written(struct extent_status *es)
     163                 :            : {
     164                 :    8501467 :         return (ext4_es_type(es) & EXTENT_STATUS_WRITTEN) != 0;
     165                 :            : }
     166                 :            : 
     167                 :            : static inline int ext4_es_is_unwritten(struct extent_status *es)
     168                 :            : {
     169                 :    5531140 :         return (ext4_es_type(es) & EXTENT_STATUS_UNWRITTEN) != 0;
     170                 :            : }
     171                 :            : 
     172                 :         62 : static inline int ext4_es_is_delayed(struct extent_status *es)
     173                 :            : {
     174                 :    1962561 :         return (ext4_es_type(es) & EXTENT_STATUS_DELAYED) != 0;
     175                 :            : }
     176                 :            : 
     177                 :            : static inline int ext4_es_is_hole(struct extent_status *es)
     178                 :            : {
     179                 :     232500 :         return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0;
     180                 :            : }
     181                 :            : 
     182                 :          0 : static inline int ext4_es_is_mapped(struct extent_status *es)
     183                 :            : {
     184   [ #  #  #  # ]:          0 :         return (ext4_es_is_written(es) || ext4_es_is_unwritten(es));
     185                 :            : }
     186                 :            : 
     187                 :          0 : static inline int ext4_es_is_delonly(struct extent_status *es)
     188                 :            : {
     189   [ -  +  #  #  :      49972 :         return (ext4_es_is_delayed(es) && !ext4_es_is_unwritten(es));
          #  #  #  #  #  
          #  #  #  +  +  
          -  +  #  #  #  
                      # ]
     190                 :            : }
     191                 :            : 
     192                 :            : static inline void ext4_es_set_referenced(struct extent_status *es)
     193                 :            : {
     194                 :     352041 :         es->es_pblk |= ((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT;
     195                 :            : }
     196                 :            : 
     197                 :            : static inline void ext4_es_clear_referenced(struct extent_status *es)
     198                 :            : {
     199                 :          0 :         es->es_pblk &= ~(((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT);
     200                 :            : }
     201                 :            : 
     202                 :            : static inline int ext4_es_is_referenced(struct extent_status *es)
     203                 :            : {
     204                 :    7932688 :         return (ext4_es_status(es) & EXTENT_STATUS_REFERENCED) != 0;
     205                 :            : }
     206                 :            : 
     207                 :            : static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es)
     208                 :            : {
     209                 :    8193661 :         return es->es_pblk & ~ES_MASK;
     210                 :            : }
     211                 :            : 
     212                 :            : static inline void ext4_es_store_pblock(struct extent_status *es,
     213                 :            :                                         ext4_fsblk_t pb)
     214                 :            : {
     215                 :            :         ext4_fsblk_t block;
     216                 :            : 
     217                 :     174778 :         block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
     218                 :     174778 :         es->es_pblk = block;
     219                 :            : }
     220                 :            : 
     221                 :            : static inline void ext4_es_store_status(struct extent_status *es,
     222                 :            :                                         unsigned int status)
     223                 :            : {
     224                 :            :         es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) |
     225                 :            :                       (es->es_pblk & ~ES_MASK);
     226                 :            : }
     227                 :            : 
     228                 :            : static inline void ext4_es_store_pblock_status(struct extent_status *es,
     229                 :            :                                                ext4_fsblk_t pb,
     230                 :            :                                                unsigned int status)
     231                 :            : {
     232                 :    2758631 :         es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) |
     233                 :    1293830 :                       (pb & ~ES_MASK);
     234                 :            : }
     235                 :            : 
     236                 :            : extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
     237                 :            : extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
     238                 :            : 
     239                 :            : extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v);
     240                 :            : 
     241                 :            : extern int __init ext4_init_pending(void);
     242                 :            : extern void ext4_exit_pending(void);
     243                 :            : extern void ext4_init_pending_tree(struct ext4_pending_tree *tree);
     244                 :            : extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk);
     245                 :            : extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk);
     246                 :            : extern int ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
     247                 :            :                                         bool allocated);
     248                 :            : extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk,
     249                 :            :                                         ext4_lblk_t len);
     250                 :            : extern void ext4_clear_inode_es(struct inode *inode);
     251                 :            : 
     252                 :            : #endif /* _EXT4_EXTENTS_STATUS_H */

Generated by: LCOV version 1.14