| 1 |
|
| 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
|