root/fs/ext4/extents_status.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. ext4_es_status
  2. ext4_es_type
  3. ext4_es_is_written
  4. ext4_es_is_unwritten
  5. ext4_es_is_delayed
  6. ext4_es_is_hole
  7. ext4_es_is_mapped
  8. ext4_es_is_delonly
  9. ext4_es_set_referenced
  10. ext4_es_clear_referenced
  11. ext4_es_is_referenced
  12. ext4_es_pblock
  13. ext4_es_store_pblock
  14. ext4_es_store_status
  15. ext4_es_store_pblock_status

   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         return es->es_pblk >> ES_SHIFT;
 155 }
 156 
 157 static inline unsigned int ext4_es_type(struct extent_status *es)
 158 {
 159         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         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         return (ext4_es_type(es) & EXTENT_STATUS_UNWRITTEN) != 0;
 170 }
 171 
 172 static inline int ext4_es_is_delayed(struct extent_status *es)
 173 {
 174         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         return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0;
 180 }
 181 
 182 static inline int ext4_es_is_mapped(struct extent_status *es)
 183 {
 184         return (ext4_es_is_written(es) || ext4_es_is_unwritten(es));
 185 }
 186 
 187 static inline int ext4_es_is_delonly(struct extent_status *es)
 188 {
 189         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         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         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         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         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         block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
 218         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         es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) |
 233                       (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 */

/* [<][>][^][v][top][bottom][index][help] */