]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/example/simple/src/ctx.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / example / simple / src / ctx.c
1 /*
2 * Copyright(c) 2019 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
4 */
5
6 #include <execinfo.h>
7 #include <ocf/ocf.h>
8 #include "ocf_env.h"
9 #include "data.h"
10 #include "volume.h"
11 #include "ctx.h"
12
13 #define PAGE_SIZE 4096
14
15 /*
16 * Allocate structure representing data for io operations.
17 */
18 ctx_data_t *ctx_data_alloc(uint32_t pages)
19 {
20 struct volume_data *data;
21
22 data = malloc(sizeof(*data));
23 data->ptr = malloc(pages * PAGE_SIZE);
24 data->offset = 0;
25
26 return data;
27 }
28
29 /*
30 * Free data structure.
31 */
32 void ctx_data_free(ctx_data_t *ctx_data)
33 {
34 struct volume_data *data = ctx_data;
35
36 if (!data)
37 return;
38
39 free(data->ptr);
40 free(data);
41 }
42
43 /*
44 * This function is supposed to set protection of data pages against swapping.
45 * Can be non-implemented if not needed.
46 */
47 static int ctx_data_mlock(ctx_data_t *ctx_data)
48 {
49 return 0;
50 }
51
52 /*
53 * Stop protecting data pages against swapping.
54 */
55 static void ctx_data_munlock(ctx_data_t *ctx_data)
56 {
57 }
58
59 /*
60 * Read data into flat memory buffer.
61 */
62 static uint32_t ctx_data_read(void *dst, ctx_data_t *src, uint32_t size)
63 {
64 struct volume_data *data = src;
65
66 memcpy(dst, data->ptr + data->offset, size);
67
68 return size;
69 }
70
71 /*
72 * Write data from flat memory buffer.
73 */
74 static uint32_t ctx_data_write(ctx_data_t *dst, const void *src, uint32_t size)
75 {
76 struct volume_data *data = dst;
77
78 memcpy(data->ptr + data->offset, src, size);
79
80 return size;
81 }
82
83 /*
84 * Fill data with zeros.
85 */
86 static uint32_t ctx_data_zero(ctx_data_t *dst, uint32_t size)
87 {
88 struct volume_data *data = dst;
89
90 memset(data->ptr + data->offset, 0, size);
91
92 return size;
93 }
94
95 /*
96 * Perform seek operation on data.
97 */
98 static uint32_t ctx_data_seek(ctx_data_t *dst, ctx_data_seek_t seek,
99 uint32_t offset)
100 {
101 struct volume_data *data = dst;
102
103 switch (seek) {
104 case ctx_data_seek_begin:
105 data->offset = offset;
106 break;
107 case ctx_data_seek_current:
108 data->offset += offset;
109 break;
110 }
111
112 return offset;
113 }
114
115 /*
116 * Copy data from one structure to another.
117 */
118 static uint64_t ctx_data_copy(ctx_data_t *dst, ctx_data_t *src,
119 uint64_t to, uint64_t from, uint64_t bytes)
120 {
121 struct volume_data *data_dst = dst;
122 struct volume_data *data_src = src;
123
124 memcpy(data_dst->ptr + to, data_src->ptr + from, bytes);
125
126 return bytes;
127 }
128
129 /*
130 * Perform secure erase of data (e.g. fill pages with zeros).
131 * Can be left non-implemented if not needed.
132 */
133 static void ctx_data_secure_erase(ctx_data_t *ctx_data)
134 {
135 }
136
137 /*
138 * Initialize cleaner thread. Cleaner thread is left non-implemented,
139 * to keep this example as simple as possible.
140 */
141 static int ctx_cleaner_init(ocf_cleaner_t c)
142 {
143 return 0;
144 }
145
146 /*
147 * Kick cleaner thread. Cleaner thread is left non-implemented,
148 * to keep this example as simple as possible.
149 */
150 static void ctx_cleaner_kick(ocf_cleaner_t c)
151 {
152 }
153
154 /*
155 * Stop cleaner thread. Cleaner thread is left non-implemented, to keep
156 * this example as simple as possible.
157 */
158 static void ctx_cleaner_stop(ocf_cleaner_t c)
159 {
160 }
161
162 /*
163 * Initialize metadata updater thread. Metadata updater thread is left
164 * non-implemented to keep this example as simple as possible.
165 */
166 static int ctx_metadata_updater_init(ocf_metadata_updater_t mu)
167 {
168 return 0;
169 }
170
171 /*
172 * Kick metadata updater thread. Metadata updater thread is left
173 * non-implemented to keep this example as simple as possible.
174 */
175 static void ctx_metadata_updater_kick(ocf_metadata_updater_t mu)
176 {
177 ocf_metadata_updater_run(mu);
178 }
179
180 /*
181 * Stop metadata updater thread. Metadata updater thread is left
182 * non-implemented to keep this example as simple as possible.
183 */
184 static void ctx_metadata_updater_stop(ocf_metadata_updater_t mu)
185 {
186 }
187
188 /*
189 * Function prividing interface for printing to log used by OCF internals.
190 * It can handle differently messages at varous log levels.
191 */
192 static int ctx_logger_print(ocf_logger_t logger, ocf_logger_lvl_t lvl,
193 const char *fmt, va_list args)
194 {
195 FILE *lfile = stdout;
196
197 if (lvl > log_info)
198 return 0;
199
200 if (lvl <= log_warn)
201 lfile = stderr;
202
203 return vfprintf(lfile, fmt, args);
204 }
205
206 #define CTX_LOG_TRACE_DEPTH 16
207
208 /*
209 * Function prividing interface for printing current stack. Used for debugging,
210 * and for providing additional information in log in case of errors.
211 */
212 static int ctx_logger_dump_stack(ocf_logger_t logger)
213 {
214 void *trace[CTX_LOG_TRACE_DEPTH];
215 char **messages = NULL;
216 int i, size;
217
218 size = backtrace(trace, CTX_LOG_TRACE_DEPTH);
219 messages = backtrace_symbols(trace, size);
220 printf("[stack trace]>>>\n");
221 for (i = 0; i < size; ++i)
222 printf("%s\n", messages[i]);
223 printf("<<<[stack trace]\n");
224 free(messages);
225
226 return 0;
227 }
228
229 /*
230 * This structure describes context config, containing simple context info
231 * and pointers to ops callbacks. Ops are splitted into few categories:
232 * - data ops, providing context specific data handing interface,
233 * - cleaner ops, providing interface to start and stop clener thread,
234 * - metadata updater ops, providing interface for starting, stoping
235 * and kicking metadata updater thread.
236 * - logger ops, providing interface for text message logging
237 */
238 static const struct ocf_ctx_config ctx_cfg = {
239 .name = "OCF Example",
240 .ops = {
241 .data = {
242 .alloc = ctx_data_alloc,
243 .free = ctx_data_free,
244 .mlock = ctx_data_mlock,
245 .munlock = ctx_data_munlock,
246 .read = ctx_data_read,
247 .write = ctx_data_write,
248 .zero = ctx_data_zero,
249 .seek = ctx_data_seek,
250 .copy = ctx_data_copy,
251 .secure_erase = ctx_data_secure_erase,
252 },
253
254 .cleaner = {
255 .init = ctx_cleaner_init,
256 .kick = ctx_cleaner_kick,
257 .stop = ctx_cleaner_stop,
258 },
259
260 .metadata_updater = {
261 .init = ctx_metadata_updater_init,
262 .kick = ctx_metadata_updater_kick,
263 .stop = ctx_metadata_updater_stop,
264 },
265
266 .logger = {
267 .print = ctx_logger_print,
268 .dump_stack = ctx_logger_dump_stack,
269 },
270 },
271 };
272
273
274 /*
275 * Function initializing context. Prepares context, sets logger and
276 * registers volume type.
277 */
278 int ctx_init(ocf_ctx_t *ctx)
279 {
280 int ret;
281
282 ret = ocf_ctx_create(ctx, &ctx_cfg);
283 if (ret)
284 return ret;
285
286 ret = volume_init(*ctx);
287 if (ret) {
288 ocf_ctx_put(*ctx);
289 return ret;
290 }
291
292 return 0;
293 }
294
295 /*
296 * Function cleaning up context. Unregisters volume type and
297 * deinitializes context.
298 */
299 void ctx_cleanup(ocf_ctx_t ctx)
300 {
301 volume_cleanup(ctx);
302 ocf_ctx_put(ctx);
303 }