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