GNU Linux-libre 4.19.211-gnu1
[releases.git] / fs / ext4 / extents_status.h
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         unsigned long es_stats_cache_hits;
74         unsigned long 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 extern int __init ext4_init_es(void);
82 extern void ext4_exit_es(void);
83 extern void ext4_es_init_tree(struct ext4_es_tree *tree);
84
85 extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
86                                  ext4_lblk_t len, ext4_fsblk_t pblk,
87                                  unsigned int status);
88 extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
89                                  ext4_lblk_t len, ext4_fsblk_t pblk,
90                                  unsigned int status);
91 extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
92                                  ext4_lblk_t len);
93 extern void ext4_es_find_delayed_extent_range(struct inode *inode,
94                                         ext4_lblk_t lblk, ext4_lblk_t end,
95                                         struct extent_status *es);
96 extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
97                                  struct extent_status *es);
98
99 static inline unsigned int ext4_es_status(struct extent_status *es)
100 {
101         return es->es_pblk >> ES_SHIFT;
102 }
103
104 static inline unsigned int ext4_es_type(struct extent_status *es)
105 {
106         return (es->es_pblk & ES_TYPE_MASK) >> ES_SHIFT;
107 }
108
109 static inline int ext4_es_is_written(struct extent_status *es)
110 {
111         return (ext4_es_type(es) & EXTENT_STATUS_WRITTEN) != 0;
112 }
113
114 static inline int ext4_es_is_unwritten(struct extent_status *es)
115 {
116         return (ext4_es_type(es) & EXTENT_STATUS_UNWRITTEN) != 0;
117 }
118
119 static inline int ext4_es_is_delayed(struct extent_status *es)
120 {
121         return (ext4_es_type(es) & EXTENT_STATUS_DELAYED) != 0;
122 }
123
124 static inline int ext4_es_is_hole(struct extent_status *es)
125 {
126         return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0;
127 }
128
129 static inline void ext4_es_set_referenced(struct extent_status *es)
130 {
131         es->es_pblk |= ((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT;
132 }
133
134 static inline void ext4_es_clear_referenced(struct extent_status *es)
135 {
136         es->es_pblk &= ~(((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT);
137 }
138
139 static inline int ext4_es_is_referenced(struct extent_status *es)
140 {
141         return (ext4_es_status(es) & EXTENT_STATUS_REFERENCED) != 0;
142 }
143
144 static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es)
145 {
146         return es->es_pblk & ~ES_MASK;
147 }
148
149 static inline void ext4_es_store_pblock(struct extent_status *es,
150                                         ext4_fsblk_t pb)
151 {
152         ext4_fsblk_t block;
153
154         block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
155         es->es_pblk = block;
156 }
157
158 static inline void ext4_es_store_status(struct extent_status *es,
159                                         unsigned int status)
160 {
161         es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) |
162                       (es->es_pblk & ~ES_MASK);
163 }
164
165 static inline void ext4_es_store_pblock_status(struct extent_status *es,
166                                                ext4_fsblk_t pb,
167                                                unsigned int status)
168 {
169         es->es_pblk = (((ext4_fsblk_t)status << ES_SHIFT) & ES_MASK) |
170                       (pb & ~ES_MASK);
171 }
172
173 extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
174 extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
175
176 extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v);
177
178 #endif /* _EXT4_EXTENTS_STATUS_H */