xref: /linux/drivers/md/dm-pcache/cache.h (revision 1d57628ff95b32d5cfa8d8f50e07690c161e9cf0)
1*1d57628fSDongsheng Yang /* SPDX-License-Identifier: GPL-2.0-or-later */
2*1d57628fSDongsheng Yang #ifndef _PCACHE_CACHE_H
3*1d57628fSDongsheng Yang #define _PCACHE_CACHE_H
4*1d57628fSDongsheng Yang 
5*1d57628fSDongsheng Yang #include "segment.h"
6*1d57628fSDongsheng Yang 
7*1d57628fSDongsheng Yang /* Garbage collection thresholds */
8*1d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_MIN       0                   /* Minimum GC percentage */
9*1d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_MAX       90                  /* Maximum GC percentage */
10*1d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_DEFAULT   70                  /* Default GC percentage */
11*1d57628fSDongsheng Yang 
12*1d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE		(4 * PCACHE_MB)     /* 4MB total tree size */
13*1d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE_MASK		0x3FFFFF            /* Mask for tree size */
14*1d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE_SHIFT		22                  /* Bit shift for tree size */
15*1d57628fSDongsheng Yang 
16*1d57628fSDongsheng Yang /* Maximum number of keys per key set */
17*1d57628fSDongsheng Yang #define PCACHE_KSET_KEYS_MAX		128
18*1d57628fSDongsheng Yang #define PCACHE_CACHE_SEGS_MAX		(1024 * 1024)	/* maximum cache size for each device is 16T */
19*1d57628fSDongsheng Yang #define PCACHE_KSET_ONMEDIA_SIZE_MAX	struct_size_t(struct pcache_cache_kset_onmedia, data, PCACHE_KSET_KEYS_MAX)
20*1d57628fSDongsheng Yang #define PCACHE_KSET_SIZE		(sizeof(struct pcache_cache_kset) + sizeof(struct pcache_cache_key_onmedia) * PCACHE_KSET_KEYS_MAX)
21*1d57628fSDongsheng Yang 
22*1d57628fSDongsheng Yang /* Maximum number of keys to clean in one round of clean_work */
23*1d57628fSDongsheng Yang #define PCACHE_CLEAN_KEYS_MAX             10
24*1d57628fSDongsheng Yang 
25*1d57628fSDongsheng Yang /* Writeback and garbage collection intervals in jiffies */
26*1d57628fSDongsheng Yang #define PCACHE_CACHE_WRITEBACK_INTERVAL   (5 * HZ)
27*1d57628fSDongsheng Yang #define PCACHE_CACHE_GC_INTERVAL          (5 * HZ)
28*1d57628fSDongsheng Yang 
29*1d57628fSDongsheng Yang /* Macro to get the cache key structure from an rb_node pointer */
30*1d57628fSDongsheng Yang #define CACHE_KEY(node)                (container_of(node, struct pcache_cache_key, rb_node))
31*1d57628fSDongsheng Yang 
32*1d57628fSDongsheng Yang struct pcache_cache_pos_onmedia {
33*1d57628fSDongsheng Yang 	struct pcache_meta_header header;
34*1d57628fSDongsheng Yang 	__u32 cache_seg_id;
35*1d57628fSDongsheng Yang 	__u32 seg_off;
36*1d57628fSDongsheng Yang };
37*1d57628fSDongsheng Yang 
38*1d57628fSDongsheng Yang /* Offset and size definitions for cache segment control */
39*1d57628fSDongsheng Yang #define PCACHE_CACHE_SEG_CTRL_OFF     (PCACHE_SEG_INFO_SIZE * PCACHE_META_INDEX_MAX)
40*1d57628fSDongsheng Yang #define PCACHE_CACHE_SEG_CTRL_SIZE    (4 * PCACHE_KB)
41*1d57628fSDongsheng Yang 
42*1d57628fSDongsheng Yang struct pcache_cache_seg_gen {
43*1d57628fSDongsheng Yang 	struct pcache_meta_header header;
44*1d57628fSDongsheng Yang 	__u64 gen;
45*1d57628fSDongsheng Yang };
46*1d57628fSDongsheng Yang 
47*1d57628fSDongsheng Yang /* Control structure for cache segments */
48*1d57628fSDongsheng Yang struct pcache_cache_seg_ctrl {
49*1d57628fSDongsheng Yang 	struct pcache_cache_seg_gen gen[PCACHE_META_INDEX_MAX];
50*1d57628fSDongsheng Yang 	__u64	res[64];
51*1d57628fSDongsheng Yang };
52*1d57628fSDongsheng Yang 
53*1d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_DATA_CRC			BIT(0)
54*1d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_INIT_DONE			BIT(1)
55*1d57628fSDongsheng Yang 
56*1d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_CACHE_MODE_MASK		GENMASK(5, 2)
57*1d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEBACK			0
58*1d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITETHROUGH			1
59*1d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEAROUND			2
60*1d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEONLY			3
61*1d57628fSDongsheng Yang 
62*1d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_GC_PERCENT_MASK		GENMASK(12, 6)
63*1d57628fSDongsheng Yang 
64*1d57628fSDongsheng Yang struct pcache_cache_info {
65*1d57628fSDongsheng Yang 	struct pcache_meta_header header;
66*1d57628fSDongsheng Yang 	__u32 seg_id;
67*1d57628fSDongsheng Yang 	__u32 n_segs;
68*1d57628fSDongsheng Yang 	__u32 flags;
69*1d57628fSDongsheng Yang 	__u32 reserved;
70*1d57628fSDongsheng Yang };
71*1d57628fSDongsheng Yang 
72*1d57628fSDongsheng Yang struct pcache_cache_pos {
73*1d57628fSDongsheng Yang 	struct pcache_cache_segment *cache_seg;
74*1d57628fSDongsheng Yang 	u32 seg_off;
75*1d57628fSDongsheng Yang };
76*1d57628fSDongsheng Yang 
77*1d57628fSDongsheng Yang struct pcache_cache_segment {
78*1d57628fSDongsheng Yang 	struct pcache_cache	*cache;
79*1d57628fSDongsheng Yang 	u32			cache_seg_id;   /* Index in cache->segments */
80*1d57628fSDongsheng Yang 	struct pcache_segment	segment;
81*1d57628fSDongsheng Yang 	atomic_t		refs;
82*1d57628fSDongsheng Yang 
83*1d57628fSDongsheng Yang 	struct pcache_segment_info cache_seg_info;
84*1d57628fSDongsheng Yang 	struct mutex		info_lock;
85*1d57628fSDongsheng Yang 	u32			info_index;
86*1d57628fSDongsheng Yang 
87*1d57628fSDongsheng Yang 	spinlock_t		gen_lock;
88*1d57628fSDongsheng Yang 	u64			gen;
89*1d57628fSDongsheng Yang 	u64			gen_seq;
90*1d57628fSDongsheng Yang 	u32			gen_index;
91*1d57628fSDongsheng Yang 
92*1d57628fSDongsheng Yang 	struct pcache_cache_seg_ctrl *cache_seg_ctrl;
93*1d57628fSDongsheng Yang 	struct mutex		ctrl_lock;
94*1d57628fSDongsheng Yang };
95*1d57628fSDongsheng Yang 
96*1d57628fSDongsheng Yang /* rbtree for cache entries */
97*1d57628fSDongsheng Yang struct pcache_cache_subtree {
98*1d57628fSDongsheng Yang 	struct rb_root root;
99*1d57628fSDongsheng Yang 	spinlock_t tree_lock;
100*1d57628fSDongsheng Yang };
101*1d57628fSDongsheng Yang 
102*1d57628fSDongsheng Yang struct pcache_cache_tree {
103*1d57628fSDongsheng Yang 	struct pcache_cache		*cache;
104*1d57628fSDongsheng Yang 	u32				n_subtrees;
105*1d57628fSDongsheng Yang 	mempool_t			key_pool;
106*1d57628fSDongsheng Yang 	struct pcache_cache_subtree	*subtrees;
107*1d57628fSDongsheng Yang };
108*1d57628fSDongsheng Yang 
109*1d57628fSDongsheng Yang extern struct kmem_cache *key_cache;
110*1d57628fSDongsheng Yang 
111*1d57628fSDongsheng Yang struct pcache_cache_key {
112*1d57628fSDongsheng Yang 	struct pcache_cache_tree	*cache_tree;
113*1d57628fSDongsheng Yang 	struct pcache_cache_subtree	*cache_subtree;
114*1d57628fSDongsheng Yang 	struct kref			ref;
115*1d57628fSDongsheng Yang 	struct rb_node			rb_node;
116*1d57628fSDongsheng Yang 	struct list_head		list_node;
117*1d57628fSDongsheng Yang 	u64				off;
118*1d57628fSDongsheng Yang 	u32				len;
119*1d57628fSDongsheng Yang 	u32				flags;
120*1d57628fSDongsheng Yang 	struct pcache_cache_pos		cache_pos;
121*1d57628fSDongsheng Yang 	u64				seg_gen;
122*1d57628fSDongsheng Yang };
123*1d57628fSDongsheng Yang 
124*1d57628fSDongsheng Yang #define PCACHE_CACHE_KEY_FLAGS_EMPTY		BIT(0)
125*1d57628fSDongsheng Yang #define PCACHE_CACHE_KEY_FLAGS_CLEAN		BIT(1)
126*1d57628fSDongsheng Yang 
127*1d57628fSDongsheng Yang struct pcache_cache_key_onmedia {
128*1d57628fSDongsheng Yang 	__u64 off;
129*1d57628fSDongsheng Yang 	__u32 len;
130*1d57628fSDongsheng Yang 	__u32 flags;
131*1d57628fSDongsheng Yang 	__u32 cache_seg_id;
132*1d57628fSDongsheng Yang 	__u32 cache_seg_off;
133*1d57628fSDongsheng Yang 	__u64 seg_gen;
134*1d57628fSDongsheng Yang 	__u32 data_crc;
135*1d57628fSDongsheng Yang 	__u32 reserved;
136*1d57628fSDongsheng Yang };
137*1d57628fSDongsheng Yang 
138*1d57628fSDongsheng Yang struct pcache_cache_kset_onmedia {
139*1d57628fSDongsheng Yang 	__u32 crc;
140*1d57628fSDongsheng Yang 	union {
141*1d57628fSDongsheng Yang 		__u32 key_num;
142*1d57628fSDongsheng Yang 		__u32 next_cache_seg_id;
143*1d57628fSDongsheng Yang 	};
144*1d57628fSDongsheng Yang 	__u64 magic;
145*1d57628fSDongsheng Yang 	__u64 flags;
146*1d57628fSDongsheng Yang 	struct pcache_cache_key_onmedia data[];
147*1d57628fSDongsheng Yang };
148*1d57628fSDongsheng Yang 
149*1d57628fSDongsheng Yang struct pcache_cache {
150*1d57628fSDongsheng Yang 	struct pcache_backing_dev	*backing_dev;
151*1d57628fSDongsheng Yang 	struct pcache_cache_dev		*cache_dev;
152*1d57628fSDongsheng Yang 	struct pcache_cache_ctrl	*cache_ctrl;
153*1d57628fSDongsheng Yang 	u64				dev_size;
154*1d57628fSDongsheng Yang 
155*1d57628fSDongsheng Yang 	struct pcache_cache_data_head __percpu *data_heads;
156*1d57628fSDongsheng Yang 
157*1d57628fSDongsheng Yang 	spinlock_t		key_head_lock;
158*1d57628fSDongsheng Yang 	struct pcache_cache_pos	key_head;
159*1d57628fSDongsheng Yang 	u32			n_ksets;
160*1d57628fSDongsheng Yang 	struct pcache_cache_kset	*ksets;
161*1d57628fSDongsheng Yang 
162*1d57628fSDongsheng Yang 	struct mutex		key_tail_lock;
163*1d57628fSDongsheng Yang 	struct pcache_cache_pos	key_tail;
164*1d57628fSDongsheng Yang 	u64			key_tail_seq;
165*1d57628fSDongsheng Yang 	u32			key_tail_index;
166*1d57628fSDongsheng Yang 
167*1d57628fSDongsheng Yang 	struct mutex		dirty_tail_lock;
168*1d57628fSDongsheng Yang 	struct pcache_cache_pos	dirty_tail;
169*1d57628fSDongsheng Yang 	u64			dirty_tail_seq;
170*1d57628fSDongsheng Yang 	u32			dirty_tail_index;
171*1d57628fSDongsheng Yang 
172*1d57628fSDongsheng Yang 	struct pcache_cache_tree	req_key_tree;
173*1d57628fSDongsheng Yang 	struct work_struct	clean_work;
174*1d57628fSDongsheng Yang 
175*1d57628fSDongsheng Yang 	struct mutex		writeback_lock;
176*1d57628fSDongsheng Yang 	char wb_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX];
177*1d57628fSDongsheng Yang 	struct pcache_cache_tree	writeback_key_tree;
178*1d57628fSDongsheng Yang 	struct delayed_work	writeback_work;
179*1d57628fSDongsheng Yang 	struct {
180*1d57628fSDongsheng Yang 		atomic_t pending;
181*1d57628fSDongsheng Yang 		u32 advance;
182*1d57628fSDongsheng Yang 		int ret;
183*1d57628fSDongsheng Yang 	} writeback_ctx;
184*1d57628fSDongsheng Yang 
185*1d57628fSDongsheng Yang 	char gc_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX];
186*1d57628fSDongsheng Yang 	struct delayed_work	gc_work;
187*1d57628fSDongsheng Yang 	atomic_t		gc_errors;
188*1d57628fSDongsheng Yang 
189*1d57628fSDongsheng Yang 	struct mutex			cache_info_lock;
190*1d57628fSDongsheng Yang 	struct pcache_cache_info	cache_info;
191*1d57628fSDongsheng Yang 	struct pcache_cache_info	*cache_info_addr;
192*1d57628fSDongsheng Yang 	u32				info_index;
193*1d57628fSDongsheng Yang 
194*1d57628fSDongsheng Yang 	u32			n_segs;
195*1d57628fSDongsheng Yang 	unsigned long		*seg_map;
196*1d57628fSDongsheng Yang 	u32			last_cache_seg;
197*1d57628fSDongsheng Yang 	bool			cache_full;
198*1d57628fSDongsheng Yang 	spinlock_t		seg_map_lock;
199*1d57628fSDongsheng Yang 	struct pcache_cache_segment *segments;
200*1d57628fSDongsheng Yang };
201*1d57628fSDongsheng Yang 
202*1d57628fSDongsheng Yang struct workqueue_struct *cache_get_wq(struct pcache_cache *cache);
203*1d57628fSDongsheng Yang 
204*1d57628fSDongsheng Yang struct dm_pcache;
205*1d57628fSDongsheng Yang struct pcache_cache_options {
206*1d57628fSDongsheng Yang 	u32	cache_mode:4;
207*1d57628fSDongsheng Yang 	u32	data_crc:1;
208*1d57628fSDongsheng Yang };
209*1d57628fSDongsheng Yang int pcache_cache_start(struct dm_pcache *pcache);
210*1d57628fSDongsheng Yang void pcache_cache_stop(struct dm_pcache *pcache);
211*1d57628fSDongsheng Yang 
212*1d57628fSDongsheng Yang struct pcache_cache_ctrl {
213*1d57628fSDongsheng Yang 	/* Updated by gc_thread */
214*1d57628fSDongsheng Yang 	struct pcache_cache_pos_onmedia key_tail_pos[PCACHE_META_INDEX_MAX];
215*1d57628fSDongsheng Yang 
216*1d57628fSDongsheng Yang 	/* Updated by writeback_thread */
217*1d57628fSDongsheng Yang 	struct pcache_cache_pos_onmedia dirty_tail_pos[PCACHE_META_INDEX_MAX];
218*1d57628fSDongsheng Yang };
219*1d57628fSDongsheng Yang 
220*1d57628fSDongsheng Yang struct pcache_cache_data_head {
221*1d57628fSDongsheng Yang 	struct pcache_cache_pos head_pos;
222*1d57628fSDongsheng Yang };
223*1d57628fSDongsheng Yang 
224*1d57628fSDongsheng Yang static inline u16 pcache_cache_get_gc_percent(struct pcache_cache *cache)
225*1d57628fSDongsheng Yang {
226*1d57628fSDongsheng Yang 	return FIELD_GET(PCACHE_CACHE_FLAGS_GC_PERCENT_MASK, cache->cache_info.flags);
227*1d57628fSDongsheng Yang }
228*1d57628fSDongsheng Yang 
229*1d57628fSDongsheng Yang int pcache_cache_set_gc_percent(struct pcache_cache *cache, u8 percent);
230*1d57628fSDongsheng Yang 
231*1d57628fSDongsheng Yang /* cache key */
232*1d57628fSDongsheng Yang struct pcache_cache_key *cache_key_alloc(struct pcache_cache_tree *cache_tree, gfp_t gfp_mask);
233*1d57628fSDongsheng Yang void cache_key_init(struct pcache_cache_tree *cache_tree, struct pcache_cache_key *key);
234*1d57628fSDongsheng Yang void cache_key_get(struct pcache_cache_key *key);
235*1d57628fSDongsheng Yang void cache_key_put(struct pcache_cache_key *key);
236*1d57628fSDongsheng Yang int cache_key_append(struct pcache_cache *cache, struct pcache_cache_key *key, bool force_close);
237*1d57628fSDongsheng Yang void cache_key_insert(struct pcache_cache_tree *cache_tree, struct pcache_cache_key *key, bool fixup);
238*1d57628fSDongsheng Yang int cache_key_decode(struct pcache_cache *cache,
239*1d57628fSDongsheng Yang 			struct pcache_cache_key_onmedia *key_onmedia,
240*1d57628fSDongsheng Yang 			struct pcache_cache_key *key);
241*1d57628fSDongsheng Yang void cache_pos_advance(struct pcache_cache_pos *pos, u32 len);
242*1d57628fSDongsheng Yang 
243*1d57628fSDongsheng Yang #define PCACHE_KSET_FLAGS_LAST		BIT(0)
244*1d57628fSDongsheng Yang #define PCACHE_KSET_MAGIC		0x676894a64e164f1aULL
245*1d57628fSDongsheng Yang 
246*1d57628fSDongsheng Yang struct pcache_cache_kset {
247*1d57628fSDongsheng Yang 	struct pcache_cache *cache;
248*1d57628fSDongsheng Yang 	spinlock_t        kset_lock;
249*1d57628fSDongsheng Yang 	struct delayed_work flush_work;
250*1d57628fSDongsheng Yang 	struct pcache_cache_kset_onmedia kset_onmedia;
251*1d57628fSDongsheng Yang };
252*1d57628fSDongsheng Yang 
253*1d57628fSDongsheng Yang extern struct pcache_cache_kset_onmedia pcache_empty_kset;
254*1d57628fSDongsheng Yang 
255*1d57628fSDongsheng Yang #define SUBTREE_WALK_RET_OK		0
256*1d57628fSDongsheng Yang #define SUBTREE_WALK_RET_ERR		1
257*1d57628fSDongsheng Yang #define SUBTREE_WALK_RET_NEED_KEY	2
258*1d57628fSDongsheng Yang #define SUBTREE_WALK_RET_NEED_REQ	3
259*1d57628fSDongsheng Yang #define SUBTREE_WALK_RET_RESEARCH	4
260*1d57628fSDongsheng Yang 
261*1d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx {
262*1d57628fSDongsheng Yang 	struct pcache_cache_tree *cache_tree;
263*1d57628fSDongsheng Yang 	struct rb_node *start_node;
264*1d57628fSDongsheng Yang 	struct pcache_request *pcache_req;
265*1d57628fSDongsheng Yang 	struct pcache_cache_key *key;
266*1d57628fSDongsheng Yang 	u32	req_done;
267*1d57628fSDongsheng Yang 	int	ret;
268*1d57628fSDongsheng Yang 
269*1d57628fSDongsheng Yang 	/* pre-allocated key and backing_dev_req */
270*1d57628fSDongsheng Yang 	struct pcache_cache_key		*pre_alloc_key;
271*1d57628fSDongsheng Yang 	struct pcache_backing_dev_req	*pre_alloc_req;
272*1d57628fSDongsheng Yang 
273*1d57628fSDongsheng Yang 	struct list_head *delete_key_list;
274*1d57628fSDongsheng Yang 	struct list_head *submit_req_list;
275*1d57628fSDongsheng Yang 
276*1d57628fSDongsheng Yang 	/*
277*1d57628fSDongsheng Yang 	 *	  |--------|		key_tmp
278*1d57628fSDongsheng Yang 	 * |====|			key
279*1d57628fSDongsheng Yang 	 */
280*1d57628fSDongsheng Yang 	int (*before)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
281*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
282*1d57628fSDongsheng Yang 
283*1d57628fSDongsheng Yang 	/*
284*1d57628fSDongsheng Yang 	 * |----------|			key_tmp
285*1d57628fSDongsheng Yang 	 *		|=====|		key
286*1d57628fSDongsheng Yang 	 */
287*1d57628fSDongsheng Yang 	int (*after)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
288*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
289*1d57628fSDongsheng Yang 
290*1d57628fSDongsheng Yang 	/*
291*1d57628fSDongsheng Yang 	 *     |----------------|	key_tmp
292*1d57628fSDongsheng Yang 	 * |===========|		key
293*1d57628fSDongsheng Yang 	 */
294*1d57628fSDongsheng Yang 	int (*overlap_tail)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
295*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
296*1d57628fSDongsheng Yang 
297*1d57628fSDongsheng Yang 	/*
298*1d57628fSDongsheng Yang 	 * |--------|			key_tmp
299*1d57628fSDongsheng Yang 	 *   |==========|		key
300*1d57628fSDongsheng Yang 	 */
301*1d57628fSDongsheng Yang 	int (*overlap_head)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
302*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
303*1d57628fSDongsheng Yang 
304*1d57628fSDongsheng Yang 	/*
305*1d57628fSDongsheng Yang 	 *    |----|			key_tmp
306*1d57628fSDongsheng Yang 	 * |==========|			key
307*1d57628fSDongsheng Yang 	 */
308*1d57628fSDongsheng Yang 	int (*overlap_contain)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
309*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
310*1d57628fSDongsheng Yang 
311*1d57628fSDongsheng Yang 	/*
312*1d57628fSDongsheng Yang 	 * |-----------|		key_tmp
313*1d57628fSDongsheng Yang 	 *   |====|			key
314*1d57628fSDongsheng Yang 	 */
315*1d57628fSDongsheng Yang 	int (*overlap_contained)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
316*1d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
317*1d57628fSDongsheng Yang 
318*1d57628fSDongsheng Yang 	int (*walk_finally)(struct pcache_cache_subtree_walk_ctx *ctx, int ret);
319*1d57628fSDongsheng Yang 	bool (*walk_done)(struct pcache_cache_subtree_walk_ctx *ctx);
320*1d57628fSDongsheng Yang };
321*1d57628fSDongsheng Yang 
322*1d57628fSDongsheng Yang int cache_subtree_walk(struct pcache_cache_subtree_walk_ctx *ctx);
323*1d57628fSDongsheng Yang struct rb_node *cache_subtree_search(struct pcache_cache_subtree *cache_subtree, struct pcache_cache_key *key,
324*1d57628fSDongsheng Yang 				  struct rb_node **parentp, struct rb_node ***newp,
325*1d57628fSDongsheng Yang 				  struct list_head *delete_key_list);
326*1d57628fSDongsheng Yang int cache_kset_close(struct pcache_cache *cache, struct pcache_cache_kset *kset);
327*1d57628fSDongsheng Yang void clean_fn(struct work_struct *work);
328*1d57628fSDongsheng Yang void kset_flush_fn(struct work_struct *work);
329*1d57628fSDongsheng Yang int cache_replay(struct pcache_cache *cache);
330*1d57628fSDongsheng Yang int cache_tree_init(struct pcache_cache *cache, struct pcache_cache_tree *cache_tree, u32 n_subtrees);
331*1d57628fSDongsheng Yang void cache_tree_clear(struct pcache_cache_tree *cache_tree);
332*1d57628fSDongsheng Yang void cache_tree_exit(struct pcache_cache_tree *cache_tree);
333*1d57628fSDongsheng Yang 
334*1d57628fSDongsheng Yang /* cache segments */
335*1d57628fSDongsheng Yang struct pcache_cache_segment *get_cache_segment(struct pcache_cache *cache);
336*1d57628fSDongsheng Yang int cache_seg_init(struct pcache_cache *cache, u32 seg_id, u32 cache_seg_id,
337*1d57628fSDongsheng Yang 		   bool new_cache);
338*1d57628fSDongsheng Yang void cache_seg_get(struct pcache_cache_segment *cache_seg);
339*1d57628fSDongsheng Yang void cache_seg_put(struct pcache_cache_segment *cache_seg);
340*1d57628fSDongsheng Yang void cache_seg_set_next_seg(struct pcache_cache_segment *cache_seg, u32 seg_id);
341*1d57628fSDongsheng Yang 
342*1d57628fSDongsheng Yang /* cache request*/
343*1d57628fSDongsheng Yang int cache_flush(struct pcache_cache *cache);
344*1d57628fSDongsheng Yang void miss_read_end_work_fn(struct work_struct *work);
345*1d57628fSDongsheng Yang int pcache_cache_handle_req(struct pcache_cache *cache, struct pcache_request *pcache_req);
346*1d57628fSDongsheng Yang 
347*1d57628fSDongsheng Yang /* gc */
348*1d57628fSDongsheng Yang void pcache_cache_gc_fn(struct work_struct *work);
349*1d57628fSDongsheng Yang 
350*1d57628fSDongsheng Yang /* writeback */
351*1d57628fSDongsheng Yang void cache_writeback_exit(struct pcache_cache *cache);
352*1d57628fSDongsheng Yang int cache_writeback_init(struct pcache_cache *cache);
353*1d57628fSDongsheng Yang void cache_writeback_fn(struct work_struct *work);
354*1d57628fSDongsheng Yang 
355*1d57628fSDongsheng Yang /* inline functions */
356*1d57628fSDongsheng Yang static inline struct pcache_cache_subtree *get_subtree(struct pcache_cache_tree *cache_tree, u64 off)
357*1d57628fSDongsheng Yang {
358*1d57628fSDongsheng Yang 	if (cache_tree->n_subtrees == 1)
359*1d57628fSDongsheng Yang 		return &cache_tree->subtrees[0];
360*1d57628fSDongsheng Yang 
361*1d57628fSDongsheng Yang 	return &cache_tree->subtrees[off >> PCACHE_CACHE_SUBTREE_SIZE_SHIFT];
362*1d57628fSDongsheng Yang }
363*1d57628fSDongsheng Yang 
364*1d57628fSDongsheng Yang static inline void *cache_pos_addr(struct pcache_cache_pos *pos)
365*1d57628fSDongsheng Yang {
366*1d57628fSDongsheng Yang 	return (pos->cache_seg->segment.data + pos->seg_off);
367*1d57628fSDongsheng Yang }
368*1d57628fSDongsheng Yang 
369*1d57628fSDongsheng Yang static inline void *get_key_head_addr(struct pcache_cache *cache)
370*1d57628fSDongsheng Yang {
371*1d57628fSDongsheng Yang 	return cache_pos_addr(&cache->key_head);
372*1d57628fSDongsheng Yang }
373*1d57628fSDongsheng Yang 
374*1d57628fSDongsheng Yang static inline u32 get_kset_id(struct pcache_cache *cache, u64 off)
375*1d57628fSDongsheng Yang {
376*1d57628fSDongsheng Yang 	u32 rem;
377*1d57628fSDongsheng Yang 	div_u64_rem(off >> PCACHE_CACHE_SUBTREE_SIZE_SHIFT, cache->n_ksets, &rem);
378*1d57628fSDongsheng Yang 	return rem;
379*1d57628fSDongsheng Yang }
380*1d57628fSDongsheng Yang 
381*1d57628fSDongsheng Yang static inline struct pcache_cache_kset *get_kset(struct pcache_cache *cache, u32 kset_id)
382*1d57628fSDongsheng Yang {
383*1d57628fSDongsheng Yang 	return (void *)cache->ksets + PCACHE_KSET_SIZE * kset_id;
384*1d57628fSDongsheng Yang }
385*1d57628fSDongsheng Yang 
386*1d57628fSDongsheng Yang static inline struct pcache_cache_data_head *get_data_head(struct pcache_cache *cache)
387*1d57628fSDongsheng Yang {
388*1d57628fSDongsheng Yang 	return this_cpu_ptr(cache->data_heads);
389*1d57628fSDongsheng Yang }
390*1d57628fSDongsheng Yang 
391*1d57628fSDongsheng Yang static inline bool cache_key_empty(struct pcache_cache_key *key)
392*1d57628fSDongsheng Yang {
393*1d57628fSDongsheng Yang 	return key->flags & PCACHE_CACHE_KEY_FLAGS_EMPTY;
394*1d57628fSDongsheng Yang }
395*1d57628fSDongsheng Yang 
396*1d57628fSDongsheng Yang static inline bool cache_key_clean(struct pcache_cache_key *key)
397*1d57628fSDongsheng Yang {
398*1d57628fSDongsheng Yang 	return key->flags & PCACHE_CACHE_KEY_FLAGS_CLEAN;
399*1d57628fSDongsheng Yang }
400*1d57628fSDongsheng Yang 
401*1d57628fSDongsheng Yang static inline void cache_pos_copy(struct pcache_cache_pos *dst, struct pcache_cache_pos *src)
402*1d57628fSDongsheng Yang {
403*1d57628fSDongsheng Yang 	memcpy(dst, src, sizeof(struct pcache_cache_pos));
404*1d57628fSDongsheng Yang }
405*1d57628fSDongsheng Yang 
406*1d57628fSDongsheng Yang /**
407*1d57628fSDongsheng Yang  * cache_seg_is_ctrl_seg - Checks if a cache segment is a cache ctrl segment.
408*1d57628fSDongsheng Yang  * @cache_seg_id: ID of the cache segment.
409*1d57628fSDongsheng Yang  *
410*1d57628fSDongsheng Yang  * Returns true if the cache segment ID corresponds to a cache ctrl segment.
411*1d57628fSDongsheng Yang  *
412*1d57628fSDongsheng Yang  * Note: We extend the segment control of the first cache segment
413*1d57628fSDongsheng Yang  * (cache segment ID 0) to serve as the cache control (pcache_cache_ctrl)
414*1d57628fSDongsheng Yang  * for the entire PCACHE cache. This function determines whether the given
415*1d57628fSDongsheng Yang  * cache segment is the one storing the pcache_cache_ctrl information.
416*1d57628fSDongsheng Yang  */
417*1d57628fSDongsheng Yang static inline bool cache_seg_is_ctrl_seg(u32 cache_seg_id)
418*1d57628fSDongsheng Yang {
419*1d57628fSDongsheng Yang 	return (cache_seg_id == 0);
420*1d57628fSDongsheng Yang }
421*1d57628fSDongsheng Yang 
422*1d57628fSDongsheng Yang /**
423*1d57628fSDongsheng Yang  * cache_key_cutfront - Cuts a specified length from the front of a cache key.
424*1d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
425*1d57628fSDongsheng Yang  * @cut_len: Length to cut from the front.
426*1d57628fSDongsheng Yang  *
427*1d57628fSDongsheng Yang  * Advances the cache key position by cut_len and adjusts offset and length accordingly.
428*1d57628fSDongsheng Yang  */
429*1d57628fSDongsheng Yang static inline void cache_key_cutfront(struct pcache_cache_key *key, u32 cut_len)
430*1d57628fSDongsheng Yang {
431*1d57628fSDongsheng Yang 	if (key->cache_pos.cache_seg)
432*1d57628fSDongsheng Yang 		cache_pos_advance(&key->cache_pos, cut_len);
433*1d57628fSDongsheng Yang 
434*1d57628fSDongsheng Yang 	key->off += cut_len;
435*1d57628fSDongsheng Yang 	key->len -= cut_len;
436*1d57628fSDongsheng Yang }
437*1d57628fSDongsheng Yang 
438*1d57628fSDongsheng Yang /**
439*1d57628fSDongsheng Yang  * cache_key_cutback - Cuts a specified length from the back of a cache key.
440*1d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
441*1d57628fSDongsheng Yang  * @cut_len: Length to cut from the back.
442*1d57628fSDongsheng Yang  *
443*1d57628fSDongsheng Yang  * Reduces the length of the cache key by cut_len.
444*1d57628fSDongsheng Yang  */
445*1d57628fSDongsheng Yang static inline void cache_key_cutback(struct pcache_cache_key *key, u32 cut_len)
446*1d57628fSDongsheng Yang {
447*1d57628fSDongsheng Yang 	key->len -= cut_len;
448*1d57628fSDongsheng Yang }
449*1d57628fSDongsheng Yang 
450*1d57628fSDongsheng Yang static inline void cache_key_delete(struct pcache_cache_key *key)
451*1d57628fSDongsheng Yang {
452*1d57628fSDongsheng Yang 	struct pcache_cache_subtree *cache_subtree;
453*1d57628fSDongsheng Yang 
454*1d57628fSDongsheng Yang 	cache_subtree = key->cache_subtree;
455*1d57628fSDongsheng Yang 	BUG_ON(!cache_subtree);
456*1d57628fSDongsheng Yang 
457*1d57628fSDongsheng Yang 	rb_erase(&key->rb_node, &cache_subtree->root);
458*1d57628fSDongsheng Yang 	key->flags = 0;
459*1d57628fSDongsheng Yang 	cache_key_put(key);
460*1d57628fSDongsheng Yang }
461*1d57628fSDongsheng Yang 
462*1d57628fSDongsheng Yang static inline bool cache_data_crc_on(struct pcache_cache *cache)
463*1d57628fSDongsheng Yang {
464*1d57628fSDongsheng Yang 	return (cache->cache_info.flags & PCACHE_CACHE_FLAGS_DATA_CRC);
465*1d57628fSDongsheng Yang }
466*1d57628fSDongsheng Yang 
467*1d57628fSDongsheng Yang static inline u32 cache_mode_get(struct pcache_cache *cache)
468*1d57628fSDongsheng Yang {
469*1d57628fSDongsheng Yang 	return FIELD_GET(PCACHE_CACHE_FLAGS_CACHE_MODE_MASK, cache->cache_info.flags);
470*1d57628fSDongsheng Yang }
471*1d57628fSDongsheng Yang 
472*1d57628fSDongsheng Yang static inline void cache_mode_set(struct pcache_cache *cache, u32 cache_mode)
473*1d57628fSDongsheng Yang {
474*1d57628fSDongsheng Yang 	cache->cache_info.flags &= ~PCACHE_CACHE_FLAGS_CACHE_MODE_MASK;
475*1d57628fSDongsheng Yang 	cache->cache_info.flags |= FIELD_PREP(PCACHE_CACHE_FLAGS_CACHE_MODE_MASK, cache_mode);
476*1d57628fSDongsheng Yang }
477*1d57628fSDongsheng Yang 
478*1d57628fSDongsheng Yang /**
479*1d57628fSDongsheng Yang  * cache_key_data_crc - Calculates CRC for data in a cache key.
480*1d57628fSDongsheng Yang  * @key: Pointer to the pcache_cache_key structure.
481*1d57628fSDongsheng Yang  *
482*1d57628fSDongsheng Yang  * Returns the CRC-32 checksum of the data within the cache key's position.
483*1d57628fSDongsheng Yang  */
484*1d57628fSDongsheng Yang static inline u32 cache_key_data_crc(struct pcache_cache_key *key)
485*1d57628fSDongsheng Yang {
486*1d57628fSDongsheng Yang 	void *data;
487*1d57628fSDongsheng Yang 
488*1d57628fSDongsheng Yang 	data = cache_pos_addr(&key->cache_pos);
489*1d57628fSDongsheng Yang 
490*1d57628fSDongsheng Yang 	return crc32c(PCACHE_CRC_SEED, data, key->len);
491*1d57628fSDongsheng Yang }
492*1d57628fSDongsheng Yang 
493*1d57628fSDongsheng Yang static inline u32 cache_kset_crc(struct pcache_cache_kset_onmedia *kset_onmedia)
494*1d57628fSDongsheng Yang {
495*1d57628fSDongsheng Yang 	u32 crc_size;
496*1d57628fSDongsheng Yang 
497*1d57628fSDongsheng Yang 	if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST)
498*1d57628fSDongsheng Yang 		crc_size = sizeof(struct pcache_cache_kset_onmedia) - 4;
499*1d57628fSDongsheng Yang 	else
500*1d57628fSDongsheng Yang 		crc_size = struct_size(kset_onmedia, data, kset_onmedia->key_num) - 4;
501*1d57628fSDongsheng Yang 
502*1d57628fSDongsheng Yang 	return crc32c(PCACHE_CRC_SEED, (void *)kset_onmedia + 4, crc_size);
503*1d57628fSDongsheng Yang }
504*1d57628fSDongsheng Yang 
505*1d57628fSDongsheng Yang static inline u32 get_kset_onmedia_size(struct pcache_cache_kset_onmedia *kset_onmedia)
506*1d57628fSDongsheng Yang {
507*1d57628fSDongsheng Yang 	return struct_size_t(struct pcache_cache_kset_onmedia, data, kset_onmedia->key_num);
508*1d57628fSDongsheng Yang }
509*1d57628fSDongsheng Yang 
510*1d57628fSDongsheng Yang /**
511*1d57628fSDongsheng Yang  * cache_seg_remain - Computes remaining space in a cache segment.
512*1d57628fSDongsheng Yang  * @pos: Pointer to pcache_cache_pos structure.
513*1d57628fSDongsheng Yang  *
514*1d57628fSDongsheng Yang  * Returns the amount of remaining space in the segment data starting from
515*1d57628fSDongsheng Yang  * the current position offset.
516*1d57628fSDongsheng Yang  */
517*1d57628fSDongsheng Yang static inline u32 cache_seg_remain(struct pcache_cache_pos *pos)
518*1d57628fSDongsheng Yang {
519*1d57628fSDongsheng Yang 	struct pcache_cache_segment *cache_seg;
520*1d57628fSDongsheng Yang 	struct pcache_segment *segment;
521*1d57628fSDongsheng Yang 	u32 seg_remain;
522*1d57628fSDongsheng Yang 
523*1d57628fSDongsheng Yang 	cache_seg = pos->cache_seg;
524*1d57628fSDongsheng Yang 	segment = &cache_seg->segment;
525*1d57628fSDongsheng Yang 	seg_remain = segment->data_size - pos->seg_off;
526*1d57628fSDongsheng Yang 
527*1d57628fSDongsheng Yang 	return seg_remain;
528*1d57628fSDongsheng Yang }
529*1d57628fSDongsheng Yang 
530*1d57628fSDongsheng Yang /**
531*1d57628fSDongsheng Yang  * cache_key_invalid - Checks if a cache key is invalid.
532*1d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
533*1d57628fSDongsheng Yang  *
534*1d57628fSDongsheng Yang  * Returns true if the cache key is invalid due to its generation being
535*1d57628fSDongsheng Yang  * less than the generation of its segment; otherwise returns false.
536*1d57628fSDongsheng Yang  *
537*1d57628fSDongsheng Yang  * When the GC (garbage collection) thread identifies a segment
538*1d57628fSDongsheng Yang  * as reclaimable, it increments the segment's generation (gen). However,
539*1d57628fSDongsheng Yang  * it does not immediately remove all related cache keys. When accessing
540*1d57628fSDongsheng Yang  * such a cache key, this function can be used to determine if the cache
541*1d57628fSDongsheng Yang  * key has already become invalid.
542*1d57628fSDongsheng Yang  */
543*1d57628fSDongsheng Yang static inline bool cache_key_invalid(struct pcache_cache_key *key)
544*1d57628fSDongsheng Yang {
545*1d57628fSDongsheng Yang 	if (cache_key_empty(key))
546*1d57628fSDongsheng Yang 		return false;
547*1d57628fSDongsheng Yang 
548*1d57628fSDongsheng Yang 	return (key->seg_gen < key->cache_pos.cache_seg->gen);
549*1d57628fSDongsheng Yang }
550*1d57628fSDongsheng Yang 
551*1d57628fSDongsheng Yang /**
552*1d57628fSDongsheng Yang  * cache_key_lstart - Retrieves the logical start offset of a cache key.
553*1d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
554*1d57628fSDongsheng Yang  *
555*1d57628fSDongsheng Yang  * Returns the logical start offset for the cache key.
556*1d57628fSDongsheng Yang  */
557*1d57628fSDongsheng Yang static inline u64 cache_key_lstart(struct pcache_cache_key *key)
558*1d57628fSDongsheng Yang {
559*1d57628fSDongsheng Yang 	return key->off;
560*1d57628fSDongsheng Yang }
561*1d57628fSDongsheng Yang 
562*1d57628fSDongsheng Yang /**
563*1d57628fSDongsheng Yang  * cache_key_lend - Retrieves the logical end offset of a cache key.
564*1d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
565*1d57628fSDongsheng Yang  *
566*1d57628fSDongsheng Yang  * Returns the logical end offset for the cache key.
567*1d57628fSDongsheng Yang  */
568*1d57628fSDongsheng Yang static inline u64 cache_key_lend(struct pcache_cache_key *key)
569*1d57628fSDongsheng Yang {
570*1d57628fSDongsheng Yang 	return key->off + key->len;
571*1d57628fSDongsheng Yang }
572*1d57628fSDongsheng Yang 
573*1d57628fSDongsheng Yang static inline void cache_key_copy(struct pcache_cache_key *key_dst, struct pcache_cache_key *key_src)
574*1d57628fSDongsheng Yang {
575*1d57628fSDongsheng Yang 	key_dst->off = key_src->off;
576*1d57628fSDongsheng Yang 	key_dst->len = key_src->len;
577*1d57628fSDongsheng Yang 	key_dst->seg_gen = key_src->seg_gen;
578*1d57628fSDongsheng Yang 	key_dst->cache_tree = key_src->cache_tree;
579*1d57628fSDongsheng Yang 	key_dst->cache_subtree = key_src->cache_subtree;
580*1d57628fSDongsheng Yang 	key_dst->flags = key_src->flags;
581*1d57628fSDongsheng Yang 
582*1d57628fSDongsheng Yang 	cache_pos_copy(&key_dst->cache_pos, &key_src->cache_pos);
583*1d57628fSDongsheng Yang }
584*1d57628fSDongsheng Yang 
585*1d57628fSDongsheng Yang /**
586*1d57628fSDongsheng Yang  * cache_pos_onmedia_crc - Calculates the CRC for an on-media cache position.
587*1d57628fSDongsheng Yang  * @pos_om: Pointer to pcache_cache_pos_onmedia structure.
588*1d57628fSDongsheng Yang  *
589*1d57628fSDongsheng Yang  * Calculates the CRC-32 checksum of the position, excluding the first 4 bytes.
590*1d57628fSDongsheng Yang  * Returns the computed CRC value.
591*1d57628fSDongsheng Yang  */
592*1d57628fSDongsheng Yang static inline u32 cache_pos_onmedia_crc(struct pcache_cache_pos_onmedia *pos_om)
593*1d57628fSDongsheng Yang {
594*1d57628fSDongsheng Yang 	return pcache_meta_crc(&pos_om->header, sizeof(struct pcache_cache_pos_onmedia));
595*1d57628fSDongsheng Yang }
596*1d57628fSDongsheng Yang 
597*1d57628fSDongsheng Yang void cache_pos_encode(struct pcache_cache *cache,
598*1d57628fSDongsheng Yang 			     struct pcache_cache_pos_onmedia *pos_onmedia,
599*1d57628fSDongsheng Yang 			     struct pcache_cache_pos *pos, u64 seq, u32 *index);
600*1d57628fSDongsheng Yang int cache_pos_decode(struct pcache_cache *cache,
601*1d57628fSDongsheng Yang 			    struct pcache_cache_pos_onmedia *pos_onmedia,
602*1d57628fSDongsheng Yang 			    struct pcache_cache_pos *pos, u64 *seq, u32 *index);
603*1d57628fSDongsheng Yang 
604*1d57628fSDongsheng Yang static inline void cache_encode_key_tail(struct pcache_cache *cache)
605*1d57628fSDongsheng Yang {
606*1d57628fSDongsheng Yang 	cache_pos_encode(cache, cache->cache_ctrl->key_tail_pos,
607*1d57628fSDongsheng Yang 			&cache->key_tail, ++cache->key_tail_seq,
608*1d57628fSDongsheng Yang 			&cache->key_tail_index);
609*1d57628fSDongsheng Yang }
610*1d57628fSDongsheng Yang 
611*1d57628fSDongsheng Yang static inline int cache_decode_key_tail(struct pcache_cache *cache)
612*1d57628fSDongsheng Yang {
613*1d57628fSDongsheng Yang 	return cache_pos_decode(cache, cache->cache_ctrl->key_tail_pos,
614*1d57628fSDongsheng Yang 				&cache->key_tail, &cache->key_tail_seq,
615*1d57628fSDongsheng Yang 				&cache->key_tail_index);
616*1d57628fSDongsheng Yang }
617*1d57628fSDongsheng Yang 
618*1d57628fSDongsheng Yang static inline void cache_encode_dirty_tail(struct pcache_cache *cache)
619*1d57628fSDongsheng Yang {
620*1d57628fSDongsheng Yang 	cache_pos_encode(cache, cache->cache_ctrl->dirty_tail_pos,
621*1d57628fSDongsheng Yang 			&cache->dirty_tail, ++cache->dirty_tail_seq,
622*1d57628fSDongsheng Yang 			&cache->dirty_tail_index);
623*1d57628fSDongsheng Yang }
624*1d57628fSDongsheng Yang 
625*1d57628fSDongsheng Yang static inline int cache_decode_dirty_tail(struct pcache_cache *cache)
626*1d57628fSDongsheng Yang {
627*1d57628fSDongsheng Yang 	return cache_pos_decode(cache, cache->cache_ctrl->dirty_tail_pos,
628*1d57628fSDongsheng Yang 				&cache->dirty_tail, &cache->dirty_tail_seq,
629*1d57628fSDongsheng Yang 				&cache->dirty_tail_index);
630*1d57628fSDongsheng Yang }
631*1d57628fSDongsheng Yang 
632*1d57628fSDongsheng Yang int pcache_cache_init(void);
633*1d57628fSDongsheng Yang void pcache_cache_exit(void);
634*1d57628fSDongsheng Yang #endif /* _PCACHE_CACHE_H */
635