xref: /linux/drivers/md/dm-pcache/backing_dev.h (revision 4f38da1f027ea2c9f01bb71daa7a299c191b6940)
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