1f5166768STheodore Ts'o // SPDX-License-Identifier: GPL-2.0 2c0677e6dSZheng Liu /* 3c0677e6dSZheng Liu * fs/ext4/extents_status.h 4c0677e6dSZheng Liu * 5c0677e6dSZheng Liu * Written by Yongqiang Yang <xiaoqiangnk@gmail.com> 6c0677e6dSZheng Liu * Modified by 7c0677e6dSZheng Liu * Allison Henderson <achender@linux.vnet.ibm.com> 8c0677e6dSZheng Liu * Zheng Liu <wenqing.lz@taobao.com> 9c0677e6dSZheng Liu * 10c0677e6dSZheng Liu */ 11c0677e6dSZheng Liu 12c0677e6dSZheng Liu #ifndef _EXT4_EXTENTS_STATUS_H 13c0677e6dSZheng Liu #define _EXT4_EXTENTS_STATUS_H 14c0677e6dSZheng Liu 15654598beSZheng Liu /* 16654598beSZheng Liu * Turn on ES_DEBUG__ to get lots of info about extent status operations. 17654598beSZheng Liu */ 18654598beSZheng Liu #ifdef ES_DEBUG__ 19654598beSZheng Liu #define es_debug(fmt, ...) printk(fmt, ##__VA_ARGS__) 20654598beSZheng Liu #else 21654598beSZheng Liu #define es_debug(fmt, ...) no_printk(fmt, ##__VA_ARGS__) 22654598beSZheng Liu #endif 23654598beSZheng Liu 248e919d13STheodore Ts'o /* 25921f266bSDmitry Monakhov * With ES_AGGRESSIVE_TEST defined, the result of es caching will be 26921f266bSDmitry Monakhov * checked with old map_block's result. 27921f266bSDmitry Monakhov */ 28921f266bSDmitry Monakhov #define ES_AGGRESSIVE_TEST__ 29921f266bSDmitry Monakhov 30921f266bSDmitry Monakhov /* 318e919d13STheodore Ts'o * These flags live in the high bits of extent_status.es_pblk 328e919d13STheodore Ts'o */ 33624d0f1dSJan Kara enum { 34624d0f1dSJan Kara ES_WRITTEN_B, 35624d0f1dSJan Kara ES_UNWRITTEN_B, 36624d0f1dSJan Kara ES_DELAYED_B, 37624d0f1dSJan Kara ES_HOLE_B, 382be12de9SJan Kara ES_REFERENCED_B, 39624d0f1dSJan Kara ES_FLAGS 40624d0f1dSJan Kara }; 413be78c73STheodore Ts'o 42624d0f1dSJan Kara #define ES_SHIFT (sizeof(ext4_fsblk_t)*8 - ES_FLAGS) 43624d0f1dSJan Kara #define ES_MASK (~((ext4_fsblk_t)0) << ES_SHIFT) 44fdc0212eSZheng Liu 45624d0f1dSJan Kara #define EXTENT_STATUS_WRITTEN (1 << ES_WRITTEN_B) 46624d0f1dSJan Kara #define EXTENT_STATUS_UNWRITTEN (1 << ES_UNWRITTEN_B) 47624d0f1dSJan Kara #define EXTENT_STATUS_DELAYED (1 << ES_DELAYED_B) 48624d0f1dSJan Kara #define EXTENT_STATUS_HOLE (1 << ES_HOLE_B) 492be12de9SJan Kara #define EXTENT_STATUS_REFERENCED (1 << ES_REFERENCED_B) 502be12de9SJan Kara 512be12de9SJan Kara #define ES_TYPE_MASK ((ext4_fsblk_t)(EXTENT_STATUS_WRITTEN | \ 522be12de9SJan Kara EXTENT_STATUS_UNWRITTEN | \ 532be12de9SJan Kara EXTENT_STATUS_DELAYED | \ 542be12de9SJan Kara EXTENT_STATUS_HOLE) << ES_SHIFT) 553be78c73STheodore Ts'o 56d3922a77SZheng Liu struct ext4_sb_info; 57adb23551SZheng Liu struct ext4_extent; 58adb23551SZheng Liu 59c0677e6dSZheng Liu struct extent_status { 60c0677e6dSZheng Liu struct rb_node rb_node; 6106b0c886SZheng Liu ext4_lblk_t es_lblk; /* first logical block extent covers */ 6206b0c886SZheng Liu ext4_lblk_t es_len; /* length of extent in block */ 63fdc0212eSZheng Liu ext4_fsblk_t es_pblk; /* first physical block */ 64c0677e6dSZheng Liu }; 65c0677e6dSZheng Liu 66c0677e6dSZheng Liu struct ext4_es_tree { 67c0677e6dSZheng Liu struct rb_root root; 68c0677e6dSZheng Liu struct extent_status *cache_es; /* recently accessed extent */ 69c0677e6dSZheng Liu }; 70c0677e6dSZheng Liu 71eb68d0e2SZheng Liu struct ext4_es_stats { 72eb68d0e2SZheng Liu unsigned long es_stats_shrunk; 73eb68d0e2SZheng Liu unsigned long es_stats_cache_hits; 74eb68d0e2SZheng Liu unsigned long es_stats_cache_misses; 75eb68d0e2SZheng Liu u64 es_stats_scan_time; 76eb68d0e2SZheng Liu u64 es_stats_max_scan_time; 77eb68d0e2SZheng Liu struct percpu_counter es_stats_all_cnt; 78edaa53caSZheng Liu struct percpu_counter es_stats_shk_cnt; 79eb68d0e2SZheng Liu }; 80eb68d0e2SZheng Liu 81654598beSZheng Liu extern int __init ext4_init_es(void); 82654598beSZheng Liu extern void ext4_exit_es(void); 83654598beSZheng Liu extern void ext4_es_init_tree(struct ext4_es_tree *tree); 84654598beSZheng Liu 8506b0c886SZheng Liu extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, 86fdc0212eSZheng Liu ext4_lblk_t len, ext4_fsblk_t pblk, 873be78c73STheodore Ts'o unsigned int status); 88107a7bd3STheodore Ts'o extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk, 89107a7bd3STheodore Ts'o ext4_lblk_t len, ext4_fsblk_t pblk, 90107a7bd3STheodore Ts'o unsigned int status); 9106b0c886SZheng Liu extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk, 92654598beSZheng Liu ext4_lblk_t len); 93ad431025SEric Whitney extern void ext4_es_find_extent_range(struct inode *inode, 94ad431025SEric Whitney int (*match_fn)(struct extent_status *es), 95e30b5dcaSYan, Zheng ext4_lblk_t lblk, ext4_lblk_t end, 96654598beSZheng Liu struct extent_status *es); 97d100eef2SZheng Liu extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk, 98d100eef2SZheng Liu struct extent_status *es); 99ad431025SEric Whitney extern bool ext4_es_scan_range(struct inode *inode, 100ad431025SEric Whitney int (*matching_fn)(struct extent_status *es), 101ad431025SEric Whitney ext4_lblk_t lblk, ext4_lblk_t end); 102ad431025SEric Whitney extern bool ext4_es_scan_clu(struct inode *inode, 103ad431025SEric Whitney int (*matching_fn)(struct extent_status *es), 104ad431025SEric Whitney ext4_lblk_t lblk); 105654598beSZheng Liu 106624d0f1dSJan Kara static inline unsigned int ext4_es_status(struct extent_status *es) 107624d0f1dSJan Kara { 108624d0f1dSJan Kara return es->es_pblk >> ES_SHIFT; 109624d0f1dSJan Kara } 110624d0f1dSJan Kara 1112be12de9SJan Kara static inline unsigned int ext4_es_type(struct extent_status *es) 1122be12de9SJan Kara { 1132be12de9SJan Kara return (es->es_pblk & ES_TYPE_MASK) >> ES_SHIFT; 1142be12de9SJan Kara } 1152be12de9SJan Kara 116fdc0212eSZheng Liu static inline int ext4_es_is_written(struct extent_status *es) 117fdc0212eSZheng Liu { 1182be12de9SJan Kara return (ext4_es_type(es) & EXTENT_STATUS_WRITTEN) != 0; 119fdc0212eSZheng Liu } 120fdc0212eSZheng Liu 121fdc0212eSZheng Liu static inline int ext4_es_is_unwritten(struct extent_status *es) 122fdc0212eSZheng Liu { 1232be12de9SJan Kara return (ext4_es_type(es) & EXTENT_STATUS_UNWRITTEN) != 0; 124fdc0212eSZheng Liu } 125fdc0212eSZheng Liu 126fdc0212eSZheng Liu static inline int ext4_es_is_delayed(struct extent_status *es) 127fdc0212eSZheng Liu { 1282be12de9SJan Kara return (ext4_es_type(es) & EXTENT_STATUS_DELAYED) != 0; 129fdc0212eSZheng Liu } 130fdc0212eSZheng Liu 131fdc0212eSZheng Liu static inline int ext4_es_is_hole(struct extent_status *es) 132fdc0212eSZheng Liu { 1332be12de9SJan Kara return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0; 1342be12de9SJan Kara } 1352be12de9SJan Kara 1362be12de9SJan Kara static inline void ext4_es_set_referenced(struct extent_status *es) 1372be12de9SJan Kara { 1382be12de9SJan Kara es->es_pblk |= ((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT; 1392be12de9SJan Kara } 1402be12de9SJan Kara 1412be12de9SJan Kara static inline void ext4_es_clear_referenced(struct extent_status *es) 1422be12de9SJan Kara { 1432be12de9SJan Kara es->es_pblk &= ~(((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT); 1442be12de9SJan Kara } 1452be12de9SJan Kara 1462be12de9SJan Kara static inline int ext4_es_is_referenced(struct extent_status *es) 1472be12de9SJan Kara { 1482be12de9SJan Kara return (ext4_es_status(es) & EXTENT_STATUS_REFERENCED) != 0; 149fdc0212eSZheng Liu } 150fdc0212eSZheng Liu 151fdc0212eSZheng Liu static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es) 152fdc0212eSZheng Liu { 1533be78c73STheodore Ts'o return es->es_pblk & ~ES_MASK; 154fdc0212eSZheng Liu } 155fdc0212eSZheng Liu 156fdc0212eSZheng Liu static inline void ext4_es_store_pblock(struct extent_status *es, 157fdc0212eSZheng Liu ext4_fsblk_t pb) 158fdc0212eSZheng Liu { 159fdc0212eSZheng Liu ext4_fsblk_t block; 160fdc0212eSZheng Liu 1613be78c73STheodore Ts'o block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK); 162fdc0212eSZheng Liu es->es_pblk = block; 163fdc0212eSZheng Liu } 164fdc0212eSZheng Liu 165fdc0212eSZheng Liu static inline void ext4_es_store_status(struct extent_status *es, 1663be78c73STheodore Ts'o unsigned int status) 167fdc0212eSZheng Liu { 168624d0f1dSJan Kara es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) | 169624d0f1dSJan Kara (es->es_pblk & ~ES_MASK); 170fdc0212eSZheng Liu } 171fdc0212eSZheng Liu 1729a6633b1STheodore Ts'o static inline void ext4_es_store_pblock_status(struct extent_status *es, 1739a6633b1STheodore Ts'o ext4_fsblk_t pb, 1749a6633b1STheodore Ts'o unsigned int status) 1759a6633b1STheodore Ts'o { 176624d0f1dSJan Kara es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) | 177624d0f1dSJan Kara (pb & ~ES_MASK); 1789a6633b1STheodore Ts'o } 1799a6633b1STheodore Ts'o 180eb68d0e2SZheng Liu extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi); 181d3922a77SZheng Liu extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); 18274cd15cdSZheng Liu 183ebd173beSTheodore Ts'o extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v); 184ebd173beSTheodore Ts'o 185c0677e6dSZheng Liu #endif /* _EXT4_EXTENTS_STATUS_H */ 186