1*1d57628fSDongsheng Yang /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*1d57628fSDongsheng Yang #ifndef _BACKING_DEV_H 3*1d57628fSDongsheng Yang #define _BACKING_DEV_H 4*1d57628fSDongsheng Yang 5*1d57628fSDongsheng Yang #include <linux/device-mapper.h> 6*1d57628fSDongsheng Yang 7*1d57628fSDongsheng Yang #include "pcache_internal.h" 8*1d57628fSDongsheng Yang 9*1d57628fSDongsheng Yang struct pcache_backing_dev_req; 10*1d57628fSDongsheng Yang typedef void (*backing_req_end_fn_t)(struct pcache_backing_dev_req *backing_req, int ret); 11*1d57628fSDongsheng Yang 12*1d57628fSDongsheng Yang #define BACKING_DEV_REQ_TYPE_REQ 1 13*1d57628fSDongsheng Yang #define BACKING_DEV_REQ_TYPE_KMEM 2 14*1d57628fSDongsheng Yang 15*1d57628fSDongsheng Yang #define BACKING_DEV_REQ_INLINE_BVECS 4 16*1d57628fSDongsheng Yang 17*1d57628fSDongsheng Yang struct pcache_request; 18*1d57628fSDongsheng Yang struct pcache_backing_dev_req { 19*1d57628fSDongsheng Yang u8 type; 20*1d57628fSDongsheng Yang struct bio bio; 21*1d57628fSDongsheng Yang struct pcache_backing_dev *backing_dev; 22*1d57628fSDongsheng Yang 23*1d57628fSDongsheng Yang void *priv_data; 24*1d57628fSDongsheng Yang backing_req_end_fn_t end_req; 25*1d57628fSDongsheng Yang 26*1d57628fSDongsheng Yang struct list_head node; 27*1d57628fSDongsheng Yang int ret; 28*1d57628fSDongsheng Yang 29*1d57628fSDongsheng Yang union { 30*1d57628fSDongsheng Yang struct { 31*1d57628fSDongsheng Yang struct pcache_request *upper_req; 32*1d57628fSDongsheng Yang u32 bio_off; 33*1d57628fSDongsheng Yang } req; 34*1d57628fSDongsheng Yang struct { 35*1d57628fSDongsheng Yang struct bio_vec inline_bvecs[BACKING_DEV_REQ_INLINE_BVECS]; 36*1d57628fSDongsheng Yang struct bio_vec *bvecs; 37*1d57628fSDongsheng Yang u32 n_vecs; 38*1d57628fSDongsheng Yang } kmem; 39*1d57628fSDongsheng Yang }; 40*1d57628fSDongsheng Yang }; 41*1d57628fSDongsheng Yang 42*1d57628fSDongsheng Yang struct pcache_backing_dev { 43*1d57628fSDongsheng Yang struct pcache_cache *cache; 44*1d57628fSDongsheng Yang 45*1d57628fSDongsheng Yang struct dm_dev *dm_dev; 46*1d57628fSDongsheng Yang mempool_t req_pool; 47*1d57628fSDongsheng Yang mempool_t bvec_pool; 48*1d57628fSDongsheng Yang 49*1d57628fSDongsheng Yang struct list_head submit_list; 50*1d57628fSDongsheng Yang spinlock_t submit_lock; 51*1d57628fSDongsheng Yang struct work_struct req_submit_work; 52*1d57628fSDongsheng Yang 53*1d57628fSDongsheng Yang struct list_head complete_list; 54*1d57628fSDongsheng Yang spinlock_t complete_lock; 55*1d57628fSDongsheng Yang struct work_struct req_complete_work; 56*1d57628fSDongsheng Yang 57*1d57628fSDongsheng Yang atomic_t inflight_reqs; 58*1d57628fSDongsheng Yang wait_queue_head_t inflight_wq; 59*1d57628fSDongsheng Yang 60*1d57628fSDongsheng Yang u64 dev_size; 61*1d57628fSDongsheng Yang }; 62*1d57628fSDongsheng Yang 63*1d57628fSDongsheng Yang struct dm_pcache; 64*1d57628fSDongsheng Yang int backing_dev_start(struct dm_pcache *pcache); 65*1d57628fSDongsheng Yang void backing_dev_stop(struct dm_pcache *pcache); 66*1d57628fSDongsheng Yang 67*1d57628fSDongsheng Yang struct pcache_backing_dev_req_opts { 68*1d57628fSDongsheng Yang u32 type; 69*1d57628fSDongsheng Yang union { 70*1d57628fSDongsheng Yang struct { 71*1d57628fSDongsheng Yang struct pcache_request *upper_req; 72*1d57628fSDongsheng Yang u32 req_off; 73*1d57628fSDongsheng Yang u32 len; 74*1d57628fSDongsheng Yang } req; 75*1d57628fSDongsheng Yang struct { 76*1d57628fSDongsheng Yang void *data; 77*1d57628fSDongsheng Yang blk_opf_t opf; 78*1d57628fSDongsheng Yang u32 len; 79*1d57628fSDongsheng Yang u64 backing_off; 80*1d57628fSDongsheng Yang } kmem; 81*1d57628fSDongsheng Yang }; 82*1d57628fSDongsheng Yang 83*1d57628fSDongsheng Yang gfp_t gfp_mask; 84*1d57628fSDongsheng Yang backing_req_end_fn_t end_fn; 85*1d57628fSDongsheng Yang void *priv_data; 86*1d57628fSDongsheng Yang }; 87*1d57628fSDongsheng Yang 88*1d57628fSDongsheng Yang static inline u32 backing_dev_req_coalesced_max_len(const void *data, u32 len) 89*1d57628fSDongsheng Yang { 90*1d57628fSDongsheng Yang const void *p = data; 91*1d57628fSDongsheng Yang u32 done = 0, in_page, to_advance; 92*1d57628fSDongsheng Yang struct page *first_page, *next_page; 93*1d57628fSDongsheng Yang 94*1d57628fSDongsheng Yang if (!is_vmalloc_addr(data)) 95*1d57628fSDongsheng Yang return len; 96*1d57628fSDongsheng Yang 97*1d57628fSDongsheng Yang first_page = vmalloc_to_page(p); 98*1d57628fSDongsheng Yang advance: 99*1d57628fSDongsheng Yang in_page = PAGE_SIZE - offset_in_page(p); 100*1d57628fSDongsheng Yang to_advance = min_t(u32, in_page, len - done); 101*1d57628fSDongsheng Yang 102*1d57628fSDongsheng Yang done += to_advance; 103*1d57628fSDongsheng Yang p += to_advance; 104*1d57628fSDongsheng Yang 105*1d57628fSDongsheng Yang if (done == len) 106*1d57628fSDongsheng Yang return done; 107*1d57628fSDongsheng Yang 108*1d57628fSDongsheng Yang next_page = vmalloc_to_page(p); 109*1d57628fSDongsheng Yang if (zone_device_pages_have_same_pgmap(first_page, next_page)) 110*1d57628fSDongsheng Yang goto advance; 111*1d57628fSDongsheng Yang 112*1d57628fSDongsheng Yang return done; 113*1d57628fSDongsheng Yang } 114*1d57628fSDongsheng Yang 115*1d57628fSDongsheng Yang void backing_dev_req_submit(struct pcache_backing_dev_req *backing_req, bool direct); 116*1d57628fSDongsheng Yang void backing_dev_req_end(struct pcache_backing_dev_req *backing_req); 117*1d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_dev_req_create(struct pcache_backing_dev *backing_dev, 118*1d57628fSDongsheng Yang struct pcache_backing_dev_req_opts *opts); 119*1d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_dev_req_alloc(struct pcache_backing_dev *backing_dev, 120*1d57628fSDongsheng Yang struct pcache_backing_dev_req_opts *opts); 121*1d57628fSDongsheng Yang void backing_dev_req_init(struct pcache_backing_dev_req *backing_req, 122*1d57628fSDongsheng Yang struct pcache_backing_dev_req_opts *opts); 123*1d57628fSDongsheng Yang void backing_dev_flush(struct pcache_backing_dev *backing_dev); 124*1d57628fSDongsheng Yang 125*1d57628fSDongsheng Yang int pcache_backing_init(void); 126*1d57628fSDongsheng Yang void pcache_backing_exit(void); 127*1d57628fSDongsheng Yang #endif /* _BACKING_DEV_H */ 128