xref: /linux/drivers/md/dm-pcache/cache.h (revision 24735771774954fa0ebbe0dfa285752647d327f0)
11d57628fSDongsheng Yang /* SPDX-License-Identifier: GPL-2.0-or-later */
21d57628fSDongsheng Yang #ifndef _PCACHE_CACHE_H
31d57628fSDongsheng Yang #define _PCACHE_CACHE_H
41d57628fSDongsheng Yang 
51d57628fSDongsheng Yang #include "segment.h"
61d57628fSDongsheng Yang 
71d57628fSDongsheng Yang /* Garbage collection thresholds */
81d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_MIN       0                   /* Minimum GC percentage */
91d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_MAX       90                  /* Maximum GC percentage */
101d57628fSDongsheng Yang #define PCACHE_CACHE_GC_PERCENT_DEFAULT   70                  /* Default GC percentage */
111d57628fSDongsheng Yang 
121d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE		(4 * PCACHE_MB)     /* 4MB total tree size */
131d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE_MASK		0x3FFFFF            /* Mask for tree size */
141d57628fSDongsheng Yang #define PCACHE_CACHE_SUBTREE_SIZE_SHIFT		22                  /* Bit shift for tree size */
151d57628fSDongsheng Yang 
161d57628fSDongsheng Yang /* Maximum number of keys per key set */
171d57628fSDongsheng Yang #define PCACHE_KSET_KEYS_MAX		128
181d57628fSDongsheng Yang #define PCACHE_CACHE_SEGS_MAX		(1024 * 1024)	/* maximum cache size for each device is 16T */
191d57628fSDongsheng Yang #define PCACHE_KSET_ONMEDIA_SIZE_MAX	struct_size_t(struct pcache_cache_kset_onmedia, data, PCACHE_KSET_KEYS_MAX)
201d57628fSDongsheng Yang #define PCACHE_KSET_SIZE		(sizeof(struct pcache_cache_kset) + sizeof(struct pcache_cache_key_onmedia) * PCACHE_KSET_KEYS_MAX)
211d57628fSDongsheng Yang 
221d57628fSDongsheng Yang /* Maximum number of keys to clean in one round of clean_work */
231d57628fSDongsheng Yang #define PCACHE_CLEAN_KEYS_MAX             10
241d57628fSDongsheng Yang 
251d57628fSDongsheng Yang /* Writeback and garbage collection intervals in jiffies */
261d57628fSDongsheng Yang #define PCACHE_CACHE_WRITEBACK_INTERVAL   (5 * HZ)
271d57628fSDongsheng Yang #define PCACHE_CACHE_GC_INTERVAL          (5 * HZ)
281d57628fSDongsheng Yang 
291d57628fSDongsheng Yang /* Macro to get the cache key structure from an rb_node pointer */
301d57628fSDongsheng Yang #define CACHE_KEY(node)                (container_of(node, struct pcache_cache_key, rb_node))
311d57628fSDongsheng Yang 
321d57628fSDongsheng Yang struct pcache_cache_pos_onmedia {
331d57628fSDongsheng Yang 	struct pcache_meta_header header;
341d57628fSDongsheng Yang 	__u32 cache_seg_id;
351d57628fSDongsheng Yang 	__u32 seg_off;
361d57628fSDongsheng Yang };
371d57628fSDongsheng Yang 
381d57628fSDongsheng Yang /* Offset and size definitions for cache segment control */
391d57628fSDongsheng Yang #define PCACHE_CACHE_SEG_CTRL_OFF     (PCACHE_SEG_INFO_SIZE * PCACHE_META_INDEX_MAX)
401d57628fSDongsheng Yang #define PCACHE_CACHE_SEG_CTRL_SIZE    (4 * PCACHE_KB)
411d57628fSDongsheng Yang 
421d57628fSDongsheng Yang struct pcache_cache_seg_gen {
431d57628fSDongsheng Yang 	struct pcache_meta_header header;
441d57628fSDongsheng Yang 	__u64 gen;
451d57628fSDongsheng Yang };
461d57628fSDongsheng Yang 
471d57628fSDongsheng Yang /* Control structure for cache segments */
481d57628fSDongsheng Yang struct pcache_cache_seg_ctrl {
491d57628fSDongsheng Yang 	struct pcache_cache_seg_gen gen[PCACHE_META_INDEX_MAX];
501d57628fSDongsheng Yang 	__u64	res[64];
511d57628fSDongsheng Yang };
521d57628fSDongsheng Yang 
531d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_DATA_CRC			BIT(0)
541d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_INIT_DONE			BIT(1)
551d57628fSDongsheng Yang 
561d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_CACHE_MODE_MASK		GENMASK(5, 2)
571d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEBACK			0
581d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITETHROUGH			1
591d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEAROUND			2
601d57628fSDongsheng Yang #define PCACHE_CACHE_MODE_WRITEONLY			3
611d57628fSDongsheng Yang 
621d57628fSDongsheng Yang #define PCACHE_CACHE_FLAGS_GC_PERCENT_MASK		GENMASK(12, 6)
631d57628fSDongsheng Yang 
641d57628fSDongsheng Yang struct pcache_cache_info {
651d57628fSDongsheng Yang 	struct pcache_meta_header header;
661d57628fSDongsheng Yang 	__u32 seg_id;
671d57628fSDongsheng Yang 	__u32 n_segs;
681d57628fSDongsheng Yang 	__u32 flags;
691d57628fSDongsheng Yang 	__u32 reserved;
701d57628fSDongsheng Yang };
711d57628fSDongsheng Yang 
721d57628fSDongsheng Yang struct pcache_cache_pos {
731d57628fSDongsheng Yang 	struct pcache_cache_segment *cache_seg;
741d57628fSDongsheng Yang 	u32 seg_off;
751d57628fSDongsheng Yang };
761d57628fSDongsheng Yang 
771d57628fSDongsheng Yang struct pcache_cache_segment {
781d57628fSDongsheng Yang 	struct pcache_cache	*cache;
791d57628fSDongsheng Yang 	u32			cache_seg_id;   /* Index in cache->segments */
801d57628fSDongsheng Yang 	struct pcache_segment	segment;
811d57628fSDongsheng Yang 	atomic_t		refs;
821d57628fSDongsheng Yang 
831d57628fSDongsheng Yang 	struct pcache_segment_info cache_seg_info;
841d57628fSDongsheng Yang 	struct mutex		info_lock;
851d57628fSDongsheng Yang 	u32			info_index;
861d57628fSDongsheng Yang 
871d57628fSDongsheng Yang 	spinlock_t		gen_lock;
881d57628fSDongsheng Yang 	u64			gen;
891d57628fSDongsheng Yang 	u64			gen_seq;
901d57628fSDongsheng Yang 	u32			gen_index;
911d57628fSDongsheng Yang 
921d57628fSDongsheng Yang 	struct pcache_cache_seg_ctrl *cache_seg_ctrl;
931d57628fSDongsheng Yang };
941d57628fSDongsheng Yang 
951d57628fSDongsheng Yang /* rbtree for cache entries */
961d57628fSDongsheng Yang struct pcache_cache_subtree {
971d57628fSDongsheng Yang 	struct rb_root root;
981d57628fSDongsheng Yang 	spinlock_t tree_lock;
991d57628fSDongsheng Yang };
1001d57628fSDongsheng Yang 
1011d57628fSDongsheng Yang struct pcache_cache_tree {
1021d57628fSDongsheng Yang 	struct pcache_cache		*cache;
1031d57628fSDongsheng Yang 	u32				n_subtrees;
1041d57628fSDongsheng Yang 	mempool_t			key_pool;
1051d57628fSDongsheng Yang 	struct pcache_cache_subtree	*subtrees;
1061d57628fSDongsheng Yang };
1071d57628fSDongsheng Yang 
1081d57628fSDongsheng Yang extern struct kmem_cache *key_cache;
1091d57628fSDongsheng Yang 
1101d57628fSDongsheng Yang struct pcache_cache_key {
1111d57628fSDongsheng Yang 	struct pcache_cache_tree	*cache_tree;
1121d57628fSDongsheng Yang 	struct pcache_cache_subtree	*cache_subtree;
1131d57628fSDongsheng Yang 	struct kref			ref;
1141d57628fSDongsheng Yang 	struct rb_node			rb_node;
1151d57628fSDongsheng Yang 	struct list_head		list_node;
1161d57628fSDongsheng Yang 	u64				off;
1171d57628fSDongsheng Yang 	u32				len;
1181d57628fSDongsheng Yang 	u32				flags;
1191d57628fSDongsheng Yang 	struct pcache_cache_pos		cache_pos;
1201d57628fSDongsheng Yang 	u64				seg_gen;
1211d57628fSDongsheng Yang };
1221d57628fSDongsheng Yang 
1231d57628fSDongsheng Yang #define PCACHE_CACHE_KEY_FLAGS_EMPTY		BIT(0)
1241d57628fSDongsheng Yang #define PCACHE_CACHE_KEY_FLAGS_CLEAN		BIT(1)
1251d57628fSDongsheng Yang 
1261d57628fSDongsheng Yang struct pcache_cache_key_onmedia {
1271d57628fSDongsheng Yang 	__u64 off;
1281d57628fSDongsheng Yang 	__u32 len;
1291d57628fSDongsheng Yang 	__u32 flags;
1301d57628fSDongsheng Yang 	__u32 cache_seg_id;
1311d57628fSDongsheng Yang 	__u32 cache_seg_off;
1321d57628fSDongsheng Yang 	__u64 seg_gen;
1331d57628fSDongsheng Yang 	__u32 data_crc;
1341d57628fSDongsheng Yang 	__u32 reserved;
1351d57628fSDongsheng Yang };
1361d57628fSDongsheng Yang 
1371d57628fSDongsheng Yang struct pcache_cache_kset_onmedia {
1381d57628fSDongsheng Yang 	__u32 crc;
1391d57628fSDongsheng Yang 	union {
1401d57628fSDongsheng Yang 		__u32 key_num;
1411d57628fSDongsheng Yang 		__u32 next_cache_seg_id;
1421d57628fSDongsheng Yang 	};
1431d57628fSDongsheng Yang 	__u64 magic;
1441d57628fSDongsheng Yang 	__u64 flags;
1451d57628fSDongsheng Yang 	struct pcache_cache_key_onmedia data[];
1461d57628fSDongsheng Yang };
1471d57628fSDongsheng Yang 
1481d57628fSDongsheng Yang struct pcache_cache {
1491d57628fSDongsheng Yang 	struct pcache_backing_dev	*backing_dev;
1501d57628fSDongsheng Yang 	struct pcache_cache_dev		*cache_dev;
1511d57628fSDongsheng Yang 	struct pcache_cache_ctrl	*cache_ctrl;
1521d57628fSDongsheng Yang 	u64				dev_size;
1531d57628fSDongsheng Yang 
1541d57628fSDongsheng Yang 	struct pcache_cache_data_head __percpu *data_heads;
1551d57628fSDongsheng Yang 
1561d57628fSDongsheng Yang 	spinlock_t		key_head_lock;
1571d57628fSDongsheng Yang 	struct pcache_cache_pos	key_head;
1581d57628fSDongsheng Yang 	u32			n_ksets;
1591d57628fSDongsheng Yang 	struct pcache_cache_kset	*ksets;
1601d57628fSDongsheng Yang 
1611d57628fSDongsheng Yang 	struct mutex		key_tail_lock;
1621d57628fSDongsheng Yang 	struct pcache_cache_pos	key_tail;
1631d57628fSDongsheng Yang 	u64			key_tail_seq;
1641d57628fSDongsheng Yang 	u32			key_tail_index;
1651d57628fSDongsheng Yang 
1661d57628fSDongsheng Yang 	struct mutex		dirty_tail_lock;
1671d57628fSDongsheng Yang 	struct pcache_cache_pos	dirty_tail;
1681d57628fSDongsheng Yang 	u64			dirty_tail_seq;
1691d57628fSDongsheng Yang 	u32			dirty_tail_index;
1701d57628fSDongsheng Yang 
1711d57628fSDongsheng Yang 	struct pcache_cache_tree	req_key_tree;
1721d57628fSDongsheng Yang 	struct work_struct	clean_work;
1731d57628fSDongsheng Yang 
1741d57628fSDongsheng Yang 	struct mutex		writeback_lock;
1751d57628fSDongsheng Yang 	char wb_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX];
1761d57628fSDongsheng Yang 	struct pcache_cache_tree	writeback_key_tree;
1771d57628fSDongsheng Yang 	struct delayed_work	writeback_work;
1781d57628fSDongsheng Yang 	struct {
1791d57628fSDongsheng Yang 		atomic_t pending;
1801d57628fSDongsheng Yang 		u32 advance;
1811d57628fSDongsheng Yang 		int ret;
1821d57628fSDongsheng Yang 	} writeback_ctx;
1831d57628fSDongsheng Yang 
1841d57628fSDongsheng Yang 	char gc_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX];
1851d57628fSDongsheng Yang 	struct delayed_work	gc_work;
1861d57628fSDongsheng Yang 	atomic_t		gc_errors;
1871d57628fSDongsheng Yang 
1881d57628fSDongsheng Yang 	struct mutex			cache_info_lock;
1891d57628fSDongsheng Yang 	struct pcache_cache_info	cache_info;
1901d57628fSDongsheng Yang 	struct pcache_cache_info	*cache_info_addr;
1911d57628fSDongsheng Yang 	u32				info_index;
1921d57628fSDongsheng Yang 
1931d57628fSDongsheng Yang 	u32			n_segs;
1941d57628fSDongsheng Yang 	unsigned long		*seg_map;
1951d57628fSDongsheng Yang 	u32			last_cache_seg;
1961d57628fSDongsheng Yang 	bool			cache_full;
1971d57628fSDongsheng Yang 	spinlock_t		seg_map_lock;
1981d57628fSDongsheng Yang 	struct pcache_cache_segment *segments;
1991d57628fSDongsheng Yang };
2001d57628fSDongsheng Yang 
2011d57628fSDongsheng Yang struct workqueue_struct *cache_get_wq(struct pcache_cache *cache);
2021d57628fSDongsheng Yang 
2031d57628fSDongsheng Yang struct dm_pcache;
2041d57628fSDongsheng Yang struct pcache_cache_options {
2051d57628fSDongsheng Yang 	u32	cache_mode:4;
2061d57628fSDongsheng Yang 	u32	data_crc:1;
2071d57628fSDongsheng Yang };
2081d57628fSDongsheng Yang int pcache_cache_start(struct dm_pcache *pcache);
2091d57628fSDongsheng Yang void pcache_cache_stop(struct dm_pcache *pcache);
2101d57628fSDongsheng Yang 
2111d57628fSDongsheng Yang struct pcache_cache_ctrl {
2121d57628fSDongsheng Yang 	/* Updated by gc_thread */
2131d57628fSDongsheng Yang 	struct pcache_cache_pos_onmedia key_tail_pos[PCACHE_META_INDEX_MAX];
2141d57628fSDongsheng Yang 
2151d57628fSDongsheng Yang 	/* Updated by writeback_thread */
2161d57628fSDongsheng Yang 	struct pcache_cache_pos_onmedia dirty_tail_pos[PCACHE_META_INDEX_MAX];
2171d57628fSDongsheng Yang };
2181d57628fSDongsheng Yang 
2191d57628fSDongsheng Yang struct pcache_cache_data_head {
2201d57628fSDongsheng Yang 	struct pcache_cache_pos head_pos;
2211d57628fSDongsheng Yang };
2221d57628fSDongsheng Yang 
2231d57628fSDongsheng Yang static inline u16 pcache_cache_get_gc_percent(struct pcache_cache *cache)
2241d57628fSDongsheng Yang {
2251d57628fSDongsheng Yang 	return FIELD_GET(PCACHE_CACHE_FLAGS_GC_PERCENT_MASK, cache->cache_info.flags);
2261d57628fSDongsheng Yang }
2271d57628fSDongsheng Yang 
2281d57628fSDongsheng Yang int pcache_cache_set_gc_percent(struct pcache_cache *cache, u8 percent);
2291d57628fSDongsheng Yang 
2301d57628fSDongsheng Yang /* cache key */
2311d57628fSDongsheng Yang struct pcache_cache_key *cache_key_alloc(struct pcache_cache_tree *cache_tree, gfp_t gfp_mask);
2321d57628fSDongsheng Yang void cache_key_init(struct pcache_cache_tree *cache_tree, struct pcache_cache_key *key);
2331d57628fSDongsheng Yang void cache_key_get(struct pcache_cache_key *key);
2341d57628fSDongsheng Yang void cache_key_put(struct pcache_cache_key *key);
2351d57628fSDongsheng Yang int cache_key_append(struct pcache_cache *cache, struct pcache_cache_key *key, bool force_close);
2361d57628fSDongsheng Yang void cache_key_insert(struct pcache_cache_tree *cache_tree, struct pcache_cache_key *key, bool fixup);
2371d57628fSDongsheng Yang int cache_key_decode(struct pcache_cache *cache,
2381d57628fSDongsheng Yang 			struct pcache_cache_key_onmedia *key_onmedia,
2391d57628fSDongsheng Yang 			struct pcache_cache_key *key);
2401d57628fSDongsheng Yang void cache_pos_advance(struct pcache_cache_pos *pos, u32 len);
2411d57628fSDongsheng Yang 
2421d57628fSDongsheng Yang #define PCACHE_KSET_FLAGS_LAST		BIT(0)
2431d57628fSDongsheng Yang #define PCACHE_KSET_MAGIC		0x676894a64e164f1aULL
2441d57628fSDongsheng Yang 
2451d57628fSDongsheng Yang struct pcache_cache_kset {
2461d57628fSDongsheng Yang 	struct pcache_cache *cache;
2471d57628fSDongsheng Yang 	spinlock_t        kset_lock;
2481d57628fSDongsheng Yang 	struct delayed_work flush_work;
2491d57628fSDongsheng Yang 	struct pcache_cache_kset_onmedia kset_onmedia;
2501d57628fSDongsheng Yang };
2511d57628fSDongsheng Yang 
2521d57628fSDongsheng Yang extern struct pcache_cache_kset_onmedia pcache_empty_kset;
2531d57628fSDongsheng Yang 
2541d57628fSDongsheng Yang #define SUBTREE_WALK_RET_OK		0
2551d57628fSDongsheng Yang #define SUBTREE_WALK_RET_ERR		1
2561d57628fSDongsheng Yang #define SUBTREE_WALK_RET_NEED_KEY	2
2571d57628fSDongsheng Yang #define SUBTREE_WALK_RET_NEED_REQ	3
2581d57628fSDongsheng Yang #define SUBTREE_WALK_RET_RESEARCH	4
2591d57628fSDongsheng Yang 
2601d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx {
2611d57628fSDongsheng Yang 	struct pcache_cache_tree *cache_tree;
2621d57628fSDongsheng Yang 	struct rb_node *start_node;
2631d57628fSDongsheng Yang 	struct pcache_request *pcache_req;
2641d57628fSDongsheng Yang 	struct pcache_cache_key *key;
2651d57628fSDongsheng Yang 	u32	req_done;
2661d57628fSDongsheng Yang 	int	ret;
2671d57628fSDongsheng Yang 
2681d57628fSDongsheng Yang 	/* pre-allocated key and backing_dev_req */
2691d57628fSDongsheng Yang 	struct pcache_cache_key		*pre_alloc_key;
2701d57628fSDongsheng Yang 	struct pcache_backing_dev_req	*pre_alloc_req;
2711d57628fSDongsheng Yang 
2721d57628fSDongsheng Yang 	struct list_head *delete_key_list;
2731d57628fSDongsheng Yang 	struct list_head *submit_req_list;
2741d57628fSDongsheng Yang 
2751d57628fSDongsheng Yang 	/*
2761d57628fSDongsheng Yang 	 *	  |--------|		key_tmp
2771d57628fSDongsheng Yang 	 * |====|			key
2781d57628fSDongsheng Yang 	 */
2791d57628fSDongsheng Yang 	int (*before)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
2801d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
2811d57628fSDongsheng Yang 
2821d57628fSDongsheng Yang 	/*
2831d57628fSDongsheng Yang 	 * |----------|			key_tmp
2841d57628fSDongsheng Yang 	 *		|=====|		key
2851d57628fSDongsheng Yang 	 */
2861d57628fSDongsheng Yang 	int (*after)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
2871d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
2881d57628fSDongsheng Yang 
2891d57628fSDongsheng Yang 	/*
2901d57628fSDongsheng Yang 	 *     |----------------|	key_tmp
2911d57628fSDongsheng Yang 	 * |===========|		key
2921d57628fSDongsheng Yang 	 */
2931d57628fSDongsheng Yang 	int (*overlap_tail)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
2941d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
2951d57628fSDongsheng Yang 
2961d57628fSDongsheng Yang 	/*
2971d57628fSDongsheng Yang 	 * |--------|			key_tmp
2981d57628fSDongsheng Yang 	 *   |==========|		key
2991d57628fSDongsheng Yang 	 */
3001d57628fSDongsheng Yang 	int (*overlap_head)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
3011d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
3021d57628fSDongsheng Yang 
3031d57628fSDongsheng Yang 	/*
3041d57628fSDongsheng Yang 	 *    |----|			key_tmp
3051d57628fSDongsheng Yang 	 * |==========|			key
3061d57628fSDongsheng Yang 	 */
3071d57628fSDongsheng Yang 	int (*overlap_contain)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
3081d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
3091d57628fSDongsheng Yang 
3101d57628fSDongsheng Yang 	/*
3111d57628fSDongsheng Yang 	 * |-----------|		key_tmp
3121d57628fSDongsheng Yang 	 *   |====|			key
3131d57628fSDongsheng Yang 	 */
3141d57628fSDongsheng Yang 	int (*overlap_contained)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp,
3151d57628fSDongsheng Yang 			struct pcache_cache_subtree_walk_ctx *ctx);
3161d57628fSDongsheng Yang 
3171d57628fSDongsheng Yang 	int (*walk_finally)(struct pcache_cache_subtree_walk_ctx *ctx, int ret);
3181d57628fSDongsheng Yang 	bool (*walk_done)(struct pcache_cache_subtree_walk_ctx *ctx);
3191d57628fSDongsheng Yang };
3201d57628fSDongsheng Yang 
3211d57628fSDongsheng Yang int cache_subtree_walk(struct pcache_cache_subtree_walk_ctx *ctx);
3221d57628fSDongsheng Yang struct rb_node *cache_subtree_search(struct pcache_cache_subtree *cache_subtree, struct pcache_cache_key *key,
3231d57628fSDongsheng Yang 				  struct rb_node **parentp, struct rb_node ***newp,
3241d57628fSDongsheng Yang 				  struct list_head *delete_key_list);
3251d57628fSDongsheng Yang int cache_kset_close(struct pcache_cache *cache, struct pcache_cache_kset *kset);
3261d57628fSDongsheng Yang void clean_fn(struct work_struct *work);
3271d57628fSDongsheng Yang void kset_flush_fn(struct work_struct *work);
3281d57628fSDongsheng Yang int cache_replay(struct pcache_cache *cache);
3291d57628fSDongsheng Yang int cache_tree_init(struct pcache_cache *cache, struct pcache_cache_tree *cache_tree, u32 n_subtrees);
3301d57628fSDongsheng Yang void cache_tree_clear(struct pcache_cache_tree *cache_tree);
3311d57628fSDongsheng Yang void cache_tree_exit(struct pcache_cache_tree *cache_tree);
3321d57628fSDongsheng Yang 
3331d57628fSDongsheng Yang /* cache segments */
3341d57628fSDongsheng Yang struct pcache_cache_segment *get_cache_segment(struct pcache_cache *cache);
3351d57628fSDongsheng Yang int cache_seg_init(struct pcache_cache *cache, u32 seg_id, u32 cache_seg_id,
3361d57628fSDongsheng Yang 		   bool new_cache);
3371d57628fSDongsheng Yang void cache_seg_get(struct pcache_cache_segment *cache_seg);
3381d57628fSDongsheng Yang void cache_seg_put(struct pcache_cache_segment *cache_seg);
3391d57628fSDongsheng Yang void cache_seg_set_next_seg(struct pcache_cache_segment *cache_seg, u32 seg_id);
3401d57628fSDongsheng Yang 
3411d57628fSDongsheng Yang /* cache request*/
3421d57628fSDongsheng Yang int cache_flush(struct pcache_cache *cache);
3431d57628fSDongsheng Yang void miss_read_end_work_fn(struct work_struct *work);
3441d57628fSDongsheng Yang int pcache_cache_handle_req(struct pcache_cache *cache, struct pcache_request *pcache_req);
3451d57628fSDongsheng Yang 
3461d57628fSDongsheng Yang /* gc */
3471d57628fSDongsheng Yang void pcache_cache_gc_fn(struct work_struct *work);
3481d57628fSDongsheng Yang 
3491d57628fSDongsheng Yang /* writeback */
3501d57628fSDongsheng Yang void cache_writeback_exit(struct pcache_cache *cache);
3511d57628fSDongsheng Yang int cache_writeback_init(struct pcache_cache *cache);
3521d57628fSDongsheng Yang void cache_writeback_fn(struct work_struct *work);
3531d57628fSDongsheng Yang 
3541d57628fSDongsheng Yang /* inline functions */
3551d57628fSDongsheng Yang static inline struct pcache_cache_subtree *get_subtree(struct pcache_cache_tree *cache_tree, u64 off)
3561d57628fSDongsheng Yang {
3571d57628fSDongsheng Yang 	if (cache_tree->n_subtrees == 1)
3581d57628fSDongsheng Yang 		return &cache_tree->subtrees[0];
3591d57628fSDongsheng Yang 
3601d57628fSDongsheng Yang 	return &cache_tree->subtrees[off >> PCACHE_CACHE_SUBTREE_SIZE_SHIFT];
3611d57628fSDongsheng Yang }
3621d57628fSDongsheng Yang 
3631d57628fSDongsheng Yang static inline void *cache_pos_addr(struct pcache_cache_pos *pos)
3641d57628fSDongsheng Yang {
3651d57628fSDongsheng Yang 	return (pos->cache_seg->segment.data + pos->seg_off);
3661d57628fSDongsheng Yang }
3671d57628fSDongsheng Yang 
3681d57628fSDongsheng Yang static inline void *get_key_head_addr(struct pcache_cache *cache)
3691d57628fSDongsheng Yang {
3701d57628fSDongsheng Yang 	return cache_pos_addr(&cache->key_head);
3711d57628fSDongsheng Yang }
3721d57628fSDongsheng Yang 
3731d57628fSDongsheng Yang static inline u32 get_kset_id(struct pcache_cache *cache, u64 off)
3741d57628fSDongsheng Yang {
375*24735771SDongsheng Yang 	u32 kset_id;
376*24735771SDongsheng Yang 
377*24735771SDongsheng Yang 	div_u64_rem(off >> PCACHE_CACHE_SUBTREE_SIZE_SHIFT, cache->n_ksets, &kset_id);
378*24735771SDongsheng Yang 
379*24735771SDongsheng Yang 	return kset_id;
3801d57628fSDongsheng Yang }
3811d57628fSDongsheng Yang 
3821d57628fSDongsheng Yang static inline struct pcache_cache_kset *get_kset(struct pcache_cache *cache, u32 kset_id)
3831d57628fSDongsheng Yang {
3841d57628fSDongsheng Yang 	return (void *)cache->ksets + PCACHE_KSET_SIZE * kset_id;
3851d57628fSDongsheng Yang }
3861d57628fSDongsheng Yang 
3871d57628fSDongsheng Yang static inline struct pcache_cache_data_head *get_data_head(struct pcache_cache *cache)
3881d57628fSDongsheng Yang {
3891d57628fSDongsheng Yang 	return this_cpu_ptr(cache->data_heads);
3901d57628fSDongsheng Yang }
3911d57628fSDongsheng Yang 
3921d57628fSDongsheng Yang static inline bool cache_key_empty(struct pcache_cache_key *key)
3931d57628fSDongsheng Yang {
3941d57628fSDongsheng Yang 	return key->flags & PCACHE_CACHE_KEY_FLAGS_EMPTY;
3951d57628fSDongsheng Yang }
3961d57628fSDongsheng Yang 
3971d57628fSDongsheng Yang static inline bool cache_key_clean(struct pcache_cache_key *key)
3981d57628fSDongsheng Yang {
3991d57628fSDongsheng Yang 	return key->flags & PCACHE_CACHE_KEY_FLAGS_CLEAN;
4001d57628fSDongsheng Yang }
4011d57628fSDongsheng Yang 
4021d57628fSDongsheng Yang static inline void cache_pos_copy(struct pcache_cache_pos *dst, struct pcache_cache_pos *src)
4031d57628fSDongsheng Yang {
4041d57628fSDongsheng Yang 	memcpy(dst, src, sizeof(struct pcache_cache_pos));
4051d57628fSDongsheng Yang }
4061d57628fSDongsheng Yang 
4071d57628fSDongsheng Yang /**
4081d57628fSDongsheng Yang  * cache_seg_is_ctrl_seg - Checks if a cache segment is a cache ctrl segment.
4091d57628fSDongsheng Yang  * @cache_seg_id: ID of the cache segment.
4101d57628fSDongsheng Yang  *
4111d57628fSDongsheng Yang  * Returns true if the cache segment ID corresponds to a cache ctrl segment.
4121d57628fSDongsheng Yang  *
4131d57628fSDongsheng Yang  * Note: We extend the segment control of the first cache segment
4141d57628fSDongsheng Yang  * (cache segment ID 0) to serve as the cache control (pcache_cache_ctrl)
4151d57628fSDongsheng Yang  * for the entire PCACHE cache. This function determines whether the given
4161d57628fSDongsheng Yang  * cache segment is the one storing the pcache_cache_ctrl information.
4171d57628fSDongsheng Yang  */
4181d57628fSDongsheng Yang static inline bool cache_seg_is_ctrl_seg(u32 cache_seg_id)
4191d57628fSDongsheng Yang {
4201d57628fSDongsheng Yang 	return (cache_seg_id == 0);
4211d57628fSDongsheng Yang }
4221d57628fSDongsheng Yang 
4231d57628fSDongsheng Yang /**
4241d57628fSDongsheng Yang  * cache_key_cutfront - Cuts a specified length from the front of a cache key.
4251d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
4261d57628fSDongsheng Yang  * @cut_len: Length to cut from the front.
4271d57628fSDongsheng Yang  *
4281d57628fSDongsheng Yang  * Advances the cache key position by cut_len and adjusts offset and length accordingly.
4291d57628fSDongsheng Yang  */
4301d57628fSDongsheng Yang static inline void cache_key_cutfront(struct pcache_cache_key *key, u32 cut_len)
4311d57628fSDongsheng Yang {
4321d57628fSDongsheng Yang 	if (key->cache_pos.cache_seg)
4331d57628fSDongsheng Yang 		cache_pos_advance(&key->cache_pos, cut_len);
4341d57628fSDongsheng Yang 
4351d57628fSDongsheng Yang 	key->off += cut_len;
4361d57628fSDongsheng Yang 	key->len -= cut_len;
4371d57628fSDongsheng Yang }
4381d57628fSDongsheng Yang 
4391d57628fSDongsheng Yang /**
4401d57628fSDongsheng Yang  * cache_key_cutback - Cuts a specified length from the back of a cache key.
4411d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
4421d57628fSDongsheng Yang  * @cut_len: Length to cut from the back.
4431d57628fSDongsheng Yang  *
4441d57628fSDongsheng Yang  * Reduces the length of the cache key by cut_len.
4451d57628fSDongsheng Yang  */
4461d57628fSDongsheng Yang static inline void cache_key_cutback(struct pcache_cache_key *key, u32 cut_len)
4471d57628fSDongsheng Yang {
4481d57628fSDongsheng Yang 	key->len -= cut_len;
4491d57628fSDongsheng Yang }
4501d57628fSDongsheng Yang 
4511d57628fSDongsheng Yang static inline void cache_key_delete(struct pcache_cache_key *key)
4521d57628fSDongsheng Yang {
4531d57628fSDongsheng Yang 	struct pcache_cache_subtree *cache_subtree;
4541d57628fSDongsheng Yang 
4551d57628fSDongsheng Yang 	cache_subtree = key->cache_subtree;
4561d57628fSDongsheng Yang 	BUG_ON(!cache_subtree);
4571d57628fSDongsheng Yang 
4581d57628fSDongsheng Yang 	rb_erase(&key->rb_node, &cache_subtree->root);
4591d57628fSDongsheng Yang 	key->flags = 0;
4601d57628fSDongsheng Yang 	cache_key_put(key);
4611d57628fSDongsheng Yang }
4621d57628fSDongsheng Yang 
4631d57628fSDongsheng Yang static inline bool cache_data_crc_on(struct pcache_cache *cache)
4641d57628fSDongsheng Yang {
4651d57628fSDongsheng Yang 	return (cache->cache_info.flags & PCACHE_CACHE_FLAGS_DATA_CRC);
4661d57628fSDongsheng Yang }
4671d57628fSDongsheng Yang 
4681d57628fSDongsheng Yang static inline u32 cache_mode_get(struct pcache_cache *cache)
4691d57628fSDongsheng Yang {
4701d57628fSDongsheng Yang 	return FIELD_GET(PCACHE_CACHE_FLAGS_CACHE_MODE_MASK, cache->cache_info.flags);
4711d57628fSDongsheng Yang }
4721d57628fSDongsheng Yang 
4731d57628fSDongsheng Yang static inline void cache_mode_set(struct pcache_cache *cache, u32 cache_mode)
4741d57628fSDongsheng Yang {
4751d57628fSDongsheng Yang 	cache->cache_info.flags &= ~PCACHE_CACHE_FLAGS_CACHE_MODE_MASK;
4761d57628fSDongsheng Yang 	cache->cache_info.flags |= FIELD_PREP(PCACHE_CACHE_FLAGS_CACHE_MODE_MASK, cache_mode);
4771d57628fSDongsheng Yang }
4781d57628fSDongsheng Yang 
4791d57628fSDongsheng Yang /**
4801d57628fSDongsheng Yang  * cache_key_data_crc - Calculates CRC for data in a cache key.
4811d57628fSDongsheng Yang  * @key: Pointer to the pcache_cache_key structure.
4821d57628fSDongsheng Yang  *
4831d57628fSDongsheng Yang  * Returns the CRC-32 checksum of the data within the cache key's position.
4841d57628fSDongsheng Yang  */
4851d57628fSDongsheng Yang static inline u32 cache_key_data_crc(struct pcache_cache_key *key)
4861d57628fSDongsheng Yang {
4871d57628fSDongsheng Yang 	void *data;
4881d57628fSDongsheng Yang 
4891d57628fSDongsheng Yang 	data = cache_pos_addr(&key->cache_pos);
4901d57628fSDongsheng Yang 
4911d57628fSDongsheng Yang 	return crc32c(PCACHE_CRC_SEED, data, key->len);
4921d57628fSDongsheng Yang }
4931d57628fSDongsheng Yang 
4941d57628fSDongsheng Yang static inline u32 cache_kset_crc(struct pcache_cache_kset_onmedia *kset_onmedia)
4951d57628fSDongsheng Yang {
4961d57628fSDongsheng Yang 	u32 crc_size;
4971d57628fSDongsheng Yang 
4981d57628fSDongsheng Yang 	if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST)
4991d57628fSDongsheng Yang 		crc_size = sizeof(struct pcache_cache_kset_onmedia) - 4;
5001d57628fSDongsheng Yang 	else
5011d57628fSDongsheng Yang 		crc_size = struct_size(kset_onmedia, data, kset_onmedia->key_num) - 4;
5021d57628fSDongsheng Yang 
5031d57628fSDongsheng Yang 	return crc32c(PCACHE_CRC_SEED, (void *)kset_onmedia + 4, crc_size);
5041d57628fSDongsheng Yang }
5051d57628fSDongsheng Yang 
5061d57628fSDongsheng Yang static inline u32 get_kset_onmedia_size(struct pcache_cache_kset_onmedia *kset_onmedia)
5071d57628fSDongsheng Yang {
5081d57628fSDongsheng Yang 	return struct_size_t(struct pcache_cache_kset_onmedia, data, kset_onmedia->key_num);
5091d57628fSDongsheng Yang }
5101d57628fSDongsheng Yang 
5111d57628fSDongsheng Yang /**
5121d57628fSDongsheng Yang  * cache_seg_remain - Computes remaining space in a cache segment.
5131d57628fSDongsheng Yang  * @pos: Pointer to pcache_cache_pos structure.
5141d57628fSDongsheng Yang  *
5151d57628fSDongsheng Yang  * Returns the amount of remaining space in the segment data starting from
5161d57628fSDongsheng Yang  * the current position offset.
5171d57628fSDongsheng Yang  */
5181d57628fSDongsheng Yang static inline u32 cache_seg_remain(struct pcache_cache_pos *pos)
5191d57628fSDongsheng Yang {
5201d57628fSDongsheng Yang 	struct pcache_cache_segment *cache_seg;
5211d57628fSDongsheng Yang 	struct pcache_segment *segment;
5221d57628fSDongsheng Yang 	u32 seg_remain;
5231d57628fSDongsheng Yang 
5241d57628fSDongsheng Yang 	cache_seg = pos->cache_seg;
5251d57628fSDongsheng Yang 	segment = &cache_seg->segment;
5261d57628fSDongsheng Yang 	seg_remain = segment->data_size - pos->seg_off;
5271d57628fSDongsheng Yang 
5281d57628fSDongsheng Yang 	return seg_remain;
5291d57628fSDongsheng Yang }
5301d57628fSDongsheng Yang 
5311d57628fSDongsheng Yang /**
5321d57628fSDongsheng Yang  * cache_key_invalid - Checks if a cache key is invalid.
5331d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
5341d57628fSDongsheng Yang  *
5351d57628fSDongsheng Yang  * Returns true if the cache key is invalid due to its generation being
5361d57628fSDongsheng Yang  * less than the generation of its segment; otherwise returns false.
5371d57628fSDongsheng Yang  *
5381d57628fSDongsheng Yang  * When the GC (garbage collection) thread identifies a segment
5391d57628fSDongsheng Yang  * as reclaimable, it increments the segment's generation (gen). However,
5401d57628fSDongsheng Yang  * it does not immediately remove all related cache keys. When accessing
5411d57628fSDongsheng Yang  * such a cache key, this function can be used to determine if the cache
5421d57628fSDongsheng Yang  * key has already become invalid.
5431d57628fSDongsheng Yang  */
5441d57628fSDongsheng Yang static inline bool cache_key_invalid(struct pcache_cache_key *key)
5451d57628fSDongsheng Yang {
5461d57628fSDongsheng Yang 	if (cache_key_empty(key))
5471d57628fSDongsheng Yang 		return false;
5481d57628fSDongsheng Yang 
5491d57628fSDongsheng Yang 	return (key->seg_gen < key->cache_pos.cache_seg->gen);
5501d57628fSDongsheng Yang }
5511d57628fSDongsheng Yang 
5521d57628fSDongsheng Yang /**
5531d57628fSDongsheng Yang  * cache_key_lstart - Retrieves the logical start offset of a cache key.
5541d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
5551d57628fSDongsheng Yang  *
5561d57628fSDongsheng Yang  * Returns the logical start offset for the cache key.
5571d57628fSDongsheng Yang  */
5581d57628fSDongsheng Yang static inline u64 cache_key_lstart(struct pcache_cache_key *key)
5591d57628fSDongsheng Yang {
5601d57628fSDongsheng Yang 	return key->off;
5611d57628fSDongsheng Yang }
5621d57628fSDongsheng Yang 
5631d57628fSDongsheng Yang /**
5641d57628fSDongsheng Yang  * cache_key_lend - Retrieves the logical end offset of a cache key.
5651d57628fSDongsheng Yang  * @key: Pointer to pcache_cache_key structure.
5661d57628fSDongsheng Yang  *
5671d57628fSDongsheng Yang  * Returns the logical end offset for the cache key.
5681d57628fSDongsheng Yang  */
5691d57628fSDongsheng Yang static inline u64 cache_key_lend(struct pcache_cache_key *key)
5701d57628fSDongsheng Yang {
5711d57628fSDongsheng Yang 	return key->off + key->len;
5721d57628fSDongsheng Yang }
5731d57628fSDongsheng Yang 
5741d57628fSDongsheng Yang static inline void cache_key_copy(struct pcache_cache_key *key_dst, struct pcache_cache_key *key_src)
5751d57628fSDongsheng Yang {
5761d57628fSDongsheng Yang 	key_dst->off = key_src->off;
5771d57628fSDongsheng Yang 	key_dst->len = key_src->len;
5781d57628fSDongsheng Yang 	key_dst->seg_gen = key_src->seg_gen;
5791d57628fSDongsheng Yang 	key_dst->cache_tree = key_src->cache_tree;
5801d57628fSDongsheng Yang 	key_dst->cache_subtree = key_src->cache_subtree;
5811d57628fSDongsheng Yang 	key_dst->flags = key_src->flags;
5821d57628fSDongsheng Yang 
5831d57628fSDongsheng Yang 	cache_pos_copy(&key_dst->cache_pos, &key_src->cache_pos);
5841d57628fSDongsheng Yang }
5851d57628fSDongsheng Yang 
5861d57628fSDongsheng Yang /**
5871d57628fSDongsheng Yang  * cache_pos_onmedia_crc - Calculates the CRC for an on-media cache position.
5881d57628fSDongsheng Yang  * @pos_om: Pointer to pcache_cache_pos_onmedia structure.
5891d57628fSDongsheng Yang  *
5901d57628fSDongsheng Yang  * Calculates the CRC-32 checksum of the position, excluding the first 4 bytes.
5911d57628fSDongsheng Yang  * Returns the computed CRC value.
5921d57628fSDongsheng Yang  */
5931d57628fSDongsheng Yang static inline u32 cache_pos_onmedia_crc(struct pcache_cache_pos_onmedia *pos_om)
5941d57628fSDongsheng Yang {
5951d57628fSDongsheng Yang 	return pcache_meta_crc(&pos_om->header, sizeof(struct pcache_cache_pos_onmedia));
5961d57628fSDongsheng Yang }
5971d57628fSDongsheng Yang 
5981d57628fSDongsheng Yang void cache_pos_encode(struct pcache_cache *cache,
5991d57628fSDongsheng Yang 			     struct pcache_cache_pos_onmedia *pos_onmedia,
6001d57628fSDongsheng Yang 			     struct pcache_cache_pos *pos, u64 seq, u32 *index);
6011d57628fSDongsheng Yang int cache_pos_decode(struct pcache_cache *cache,
6021d57628fSDongsheng Yang 			    struct pcache_cache_pos_onmedia *pos_onmedia,
6031d57628fSDongsheng Yang 			    struct pcache_cache_pos *pos, u64 *seq, u32 *index);
6041d57628fSDongsheng Yang 
6051d57628fSDongsheng Yang static inline void cache_encode_key_tail(struct pcache_cache *cache)
6061d57628fSDongsheng Yang {
6071d57628fSDongsheng Yang 	cache_pos_encode(cache, cache->cache_ctrl->key_tail_pos,
6081d57628fSDongsheng Yang 			&cache->key_tail, ++cache->key_tail_seq,
6091d57628fSDongsheng Yang 			&cache->key_tail_index);
6101d57628fSDongsheng Yang }
6111d57628fSDongsheng Yang 
6121d57628fSDongsheng Yang static inline int cache_decode_key_tail(struct pcache_cache *cache)
6131d57628fSDongsheng Yang {
6141d57628fSDongsheng Yang 	return cache_pos_decode(cache, cache->cache_ctrl->key_tail_pos,
6151d57628fSDongsheng Yang 				&cache->key_tail, &cache->key_tail_seq,
6161d57628fSDongsheng Yang 				&cache->key_tail_index);
6171d57628fSDongsheng Yang }
6181d57628fSDongsheng Yang 
6191d57628fSDongsheng Yang static inline void cache_encode_dirty_tail(struct pcache_cache *cache)
6201d57628fSDongsheng Yang {
6211d57628fSDongsheng Yang 	cache_pos_encode(cache, cache->cache_ctrl->dirty_tail_pos,
6221d57628fSDongsheng Yang 			&cache->dirty_tail, ++cache->dirty_tail_seq,
6231d57628fSDongsheng Yang 			&cache->dirty_tail_index);
6241d57628fSDongsheng Yang }
6251d57628fSDongsheng Yang 
6261d57628fSDongsheng Yang static inline int cache_decode_dirty_tail(struct pcache_cache *cache)
6271d57628fSDongsheng Yang {
6281d57628fSDongsheng Yang 	return cache_pos_decode(cache, cache->cache_ctrl->dirty_tail_pos,
6291d57628fSDongsheng Yang 				&cache->dirty_tail, &cache->dirty_tail_seq,
6301d57628fSDongsheng Yang 				&cache->dirty_tail_index);
6311d57628fSDongsheng Yang }
6321d57628fSDongsheng Yang 
6331d57628fSDongsheng Yang int pcache_cache_init(void);
6341d57628fSDongsheng Yang void pcache_cache_exit(void);
6351d57628fSDongsheng Yang #endif /* _PCACHE_CACHE_H */
636