Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
9struct pcache_backing_dev_req;
10typedef 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
17struct pcache_request;
18struct 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
42struct 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
63struct dm_pcache;
64int backing_dev_start(struct dm_pcache *pcache);
65void backing_dev_stop(struct dm_pcache *pcache);
66
67struct 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
88static 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);
98advance:
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
115void backing_dev_req_submit(struct pcache_backing_dev_req *backing_req, bool direct);
116void backing_dev_req_end(struct pcache_backing_dev_req *backing_req);
117struct pcache_backing_dev_req *backing_dev_req_create(struct pcache_backing_dev *backing_dev,
118 struct pcache_backing_dev_req_opts *opts);
119struct pcache_backing_dev_req *backing_dev_req_alloc(struct pcache_backing_dev *backing_dev,
120 struct pcache_backing_dev_req_opts *opts);
121void backing_dev_req_init(struct pcache_backing_dev_req *backing_req,
122 struct pcache_backing_dev_req_opts *opts);
123void backing_dev_flush(struct pcache_backing_dev *backing_dev);
124
125int pcache_backing_init(void);
126void pcache_backing_exit(void);
127#endif /* _BACKING_DEV_H */