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