]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/src/ocf_io.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / src / ocf_io.c
1 /*
2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
4 */
5
6 #include "ocf/ocf.h"
7 #include "ocf_def_priv.h"
8 #include "ocf_io_priv.h"
9 #include "ocf_volume_priv.h"
10 #include "utils/utils_io_allocator.h"
11
12 /*
13 * This is io allocator dedicated for bottom devices.
14 * Out IO structure looks like this:
15 * --------------> +-------------------------+
16 * | OCF is aware | |
17 * | of this part. | struct ocf_io_meta |
18 * | | |
19 * | +-------------------------+ <----------------
20 * | | | Bottom adapter |
21 * | | struct ocf_io | is aware of |
22 * | | | this part. |
23 * --------------> +-------------------------+ |
24 * | | |
25 * | Bottom adapter specific | |
26 * | context data structure. | |
27 * | | |
28 * +-------------------------+ <----------------
29 */
30
31 #define OCF_IO_TOTAL(priv_size) \
32 (sizeof(struct ocf_io_internal) + priv_size)
33
34 static int ocf_io_allocator_default_init(ocf_io_allocator_t allocator,
35 uint32_t priv_size, const char *name)
36 {
37 allocator->priv = env_allocator_create(OCF_IO_TOTAL(priv_size), name);
38 if (!allocator->priv)
39 return -OCF_ERR_NO_MEM;
40
41 return 0;
42 }
43
44 static void ocf_io_allocator_default_deinit(ocf_io_allocator_t allocator)
45 {
46 env_allocator_destroy(allocator->priv);
47 allocator->priv = NULL;
48 }
49
50 static void *ocf_io_allocator_default_new(ocf_io_allocator_t allocator,
51 ocf_volume_t volume, ocf_queue_t queue,
52 uint64_t addr, uint32_t bytes, uint32_t dir)
53 {
54 return env_allocator_new(allocator->priv);
55 }
56
57 static void ocf_io_allocator_default_del(ocf_io_allocator_t allocator, void *obj)
58 {
59 env_allocator_del(allocator->priv, obj);
60 }
61
62 const struct ocf_io_allocator_type type_default = {
63 .ops = {
64 .allocator_init = ocf_io_allocator_default_init,
65 .allocator_deinit = ocf_io_allocator_default_deinit,
66 .allocator_new = ocf_io_allocator_default_new,
67 .allocator_del = ocf_io_allocator_default_del,
68 },
69 };
70
71 ocf_io_allocator_type_t ocf_io_allocator_get_type_default(void)
72 {
73 return &type_default;
74 }
75
76 /*
77 * IO internal API
78 */
79
80 static struct ocf_io_internal *ocf_io_get_internal(struct ocf_io* io)
81 {
82 return container_of(io, struct ocf_io_internal, io);
83 }
84
85 struct ocf_io *ocf_io_new(ocf_volume_t volume, ocf_queue_t queue,
86 uint64_t addr, uint32_t bytes, uint32_t dir,
87 uint32_t io_class, uint64_t flags)
88 {
89 struct ocf_io_internal *ioi;
90 uint32_t sector_size = SECTORS_TO_BYTES(1);
91
92 if ((addr % sector_size) || (bytes % sector_size))
93 return NULL;
94
95 if (!ocf_refcnt_inc(&volume->refcnt))
96 return NULL;
97
98 ioi = ocf_io_allocator_new(&volume->type->allocator, volume, queue,
99 addr, bytes, dir);
100 if (!ioi) {
101 ocf_refcnt_dec(&volume->refcnt);
102 return NULL;
103 }
104
105 ioi->meta.volume = volume;
106 ioi->meta.ops = &volume->type->properties->io_ops;
107 env_atomic_set(&ioi->meta.ref_count, 1);
108
109 ioi->io.io_queue = queue;
110 ioi->io.addr = addr;
111 ioi->io.bytes = bytes;
112 ioi->io.dir = dir;
113 ioi->io.io_class = io_class;
114 ioi->io.flags = flags;
115
116 return &ioi->io;
117 }
118
119 /*
120 * IO external API
121 */
122
123 void *ocf_io_get_priv(struct ocf_io* io)
124 {
125 return (void *)io + sizeof(struct ocf_io);
126 }
127
128 int ocf_io_set_data(struct ocf_io *io, ctx_data_t *data, uint32_t offset)
129 {
130 struct ocf_io_internal *ioi = ocf_io_get_internal(io);
131
132 return ioi->meta.ops->set_data(io, data, offset);
133 }
134
135 ctx_data_t *ocf_io_get_data(struct ocf_io *io)
136 {
137 struct ocf_io_internal *ioi = ocf_io_get_internal(io);
138
139 return ioi->meta.ops->get_data(io);
140 }
141
142 void ocf_io_get(struct ocf_io *io)
143 {
144 struct ocf_io_internal *ioi = ocf_io_get_internal(io);
145
146 env_atomic_inc_return(&ioi->meta.ref_count);
147 }
148
149 void ocf_io_put(struct ocf_io *io)
150 {
151 struct ocf_io_internal *ioi = ocf_io_get_internal(io);
152
153 if (env_atomic_dec_return(&ioi->meta.ref_count))
154 return;
155
156 ocf_refcnt_dec(&ioi->meta.volume->refcnt);
157
158 ocf_io_allocator_del(&ioi->meta.volume->type->allocator, (void *)ioi);
159 }
160
161 ocf_volume_t ocf_io_get_volume(struct ocf_io *io)
162 {
163 struct ocf_io_internal *ioi = ocf_io_get_internal(io);
164
165 return ioi->meta.volume;
166 }