Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/queue.h"
7 : : #include "spdk/assert.h"
8 : : #include "spdk/env.h"
9 : :
10 : : #include "ftl_mngt.h"
11 : : #include "ftl_core.h"
12 : :
13 : : struct ftl_mngt_step_status {
14 : : uint64_t start;
15 : : uint64_t stop;
16 : : int status;
17 : : int silent;
18 : : TAILQ_ENTRY(ftl_mngt_step) entry;
19 : : };
20 : :
21 : : struct ftl_mngt_step {
22 : : void *ctx;
23 : : const struct ftl_mngt_step_desc *desc;
24 : : struct ftl_mngt_step_status action;
25 : : struct ftl_mngt_step_status rollback;
26 : : };
27 : :
28 : : struct ftl_mngt_process {
29 : : struct spdk_ftl_dev *dev;
30 : : int status;
31 : : bool silent;
32 : : bool rollback;
33 : : bool continuing;
34 : : struct {
35 : : ftl_mngt_completion cb;
36 : : void *cb_ctx;
37 : : struct spdk_thread *thread;
38 : : } caller;
39 : : void *ctx;
40 : : uint64_t tsc_start;
41 : : uint64_t tsc_stop;
42 : : const struct ftl_mngt_process_desc *desc;
43 : : TAILQ_HEAD(, ftl_mngt_step) action_queue_todo;
44 : : TAILQ_HEAD(, ftl_mngt_step) action_queue_done;
45 : : TAILQ_HEAD(, ftl_mngt_step) rollback_queue_todo;
46 : : TAILQ_HEAD(, ftl_mngt_step) rollback_queue_done;
47 : : struct {
48 : : struct ftl_mngt_step step;
49 : : struct ftl_mngt_step_desc desc;
50 : : } cleanup;
51 : : struct ftl_mng_tracer *tracer;
52 : : };
53 : :
54 : : static void action_next(struct ftl_mngt_process *mngt);
55 : : static void action_msg(void *ctx);
56 : : static void action_execute(struct ftl_mngt_process *mngt);
57 : : static void action_done(struct ftl_mngt_process *mngt, int status);
58 : : static void rollback_next(struct ftl_mngt_process *mngt);
59 : : static void rollback_msg(void *ctx);
60 : : static void rollback_execute(struct ftl_mngt_process *mngt);
61 : : static void rollback_done(struct ftl_mngt_process *mngt, int status);
62 : :
63 : : static inline struct ftl_mngt_step *
64 : 1907 : get_current_step(struct ftl_mngt_process *mngt)
65 : : {
66 [ - + + + : 1907 : if (!mngt->rollback) {
# # # # ]
67 [ # # # # : 1850 : return TAILQ_FIRST(&mngt->action_queue_todo);
# # ]
68 : : } else {
69 [ # # # # : 57 : return TAILQ_FIRST(&mngt->rollback_queue_todo);
# # ]
70 : : }
71 : 0 : }
72 : :
73 : : static int
74 : 1976 : init_step(struct ftl_mngt_process *mngt,
75 : : const struct ftl_mngt_step_desc *desc)
76 : : {
77 : : struct ftl_mngt_step *step;
78 : :
79 : 1976 : step = calloc(1, sizeof(*step));
80 [ - + ]: 1976 : if (!step) {
81 : 0 : return -ENOMEM;
82 : : }
83 : :
84 : : /* Initialize the step's argument */
85 [ + + # # : 1976 : if (desc->ctx_size) {
# # ]
86 [ # # # # : 31 : step->ctx = calloc(1, desc->ctx_size);
# # # # ]
87 [ - + # # : 31 : if (!step->ctx) {
# # ]
88 : 0 : free(step);
89 : 0 : return -ENOMEM;
90 : : }
91 : 0 : }
92 [ # # # # ]: 1976 : step->desc = desc;
93 [ # # # # : 1976 : TAILQ_INSERT_TAIL(&mngt->action_queue_todo, step, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
94 : :
95 : 1976 : return 0;
96 : 0 : }
97 : :
98 : : static void
99 : 300 : free_mngt(struct ftl_mngt_process *mngt)
100 : : {
101 : 300 : TAILQ_HEAD(, ftl_mngt_step) steps;
102 : :
103 [ - + ]: 300 : if (!mngt) {
104 : 0 : return;
105 : : }
106 : :
107 [ # # ]: 300 : TAILQ_INIT(&steps);
108 [ + + # # : 300 : TAILQ_CONCAT(&steps, &mngt->action_queue_todo, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
109 [ + + # # : 300 : TAILQ_CONCAT(&steps, &mngt->action_queue_done, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
110 : :
111 [ + + ]: 2276 : while (!TAILQ_EMPTY(&steps)) {
112 : 1976 : struct ftl_mngt_step *step = TAILQ_FIRST(&steps);
113 [ + + # # : 1976 : TAILQ_REMOVE(&steps, step, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
114 : :
115 [ # # # # ]: 1976 : free(step->ctx);
116 : 1976 : free(step);
117 : : }
118 : :
119 [ # # # # ]: 300 : free(mngt->ctx);
120 : 300 : free(mngt);
121 : 0 : }
122 : :
123 : : static struct ftl_mngt_process *
124 : 300 : allocate_mngt(struct spdk_ftl_dev *dev, const struct ftl_mngt_process_desc *pdesc,
125 : : ftl_mngt_completion cb, void *cb_ctx, bool silent)
126 : : {
127 : : struct ftl_mngt_process *mngt;
128 : :
129 : : /* Initialize management process */
130 : 300 : mngt = calloc(1, sizeof(*mngt));
131 [ - + ]: 300 : if (!mngt) {
132 : 0 : goto error;
133 : : }
134 [ # # # # ]: 300 : mngt->dev = dev;
135 [ # # # # : 300 : mngt->silent = silent;
# # ]
136 [ # # # # : 300 : mngt->caller.cb = cb;
# # ]
137 [ # # # # : 300 : mngt->caller.cb_ctx = cb_ctx;
# # ]
138 [ # # # # : 300 : mngt->caller.thread = spdk_get_thread();
# # ]
139 : :
140 : : /* Initialize process context */
141 [ + + # # : 300 : if (pdesc->ctx_size) {
# # ]
142 [ # # # # : 46 : mngt->ctx = calloc(1, pdesc->ctx_size);
# # # # ]
143 [ - + # # : 46 : if (!mngt->ctx) {
# # ]
144 : 0 : goto error;
145 : : }
146 : 0 : }
147 [ # # # # ]: 300 : mngt->tsc_start = spdk_get_ticks();
148 [ # # # # ]: 300 : mngt->desc = pdesc;
149 [ # # # # : 300 : TAILQ_INIT(&mngt->action_queue_todo);
# # # # #
# # # # #
# # ]
150 [ # # # # : 300 : TAILQ_INIT(&mngt->action_queue_done);
# # # # #
# # # # #
# # ]
151 [ # # # # : 300 : TAILQ_INIT(&mngt->rollback_queue_todo);
# # # # #
# # # # #
# # ]
152 [ # # # # : 300 : TAILQ_INIT(&mngt->rollback_queue_done);
# # # # #
# # # # #
# # ]
153 : :
154 : 300 : return mngt;
155 : 0 : error:
156 : 0 : free_mngt(mngt);
157 : 0 : return NULL;
158 : 0 : }
159 : :
160 : : static int
161 : 255 : invoke_init_handler(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
162 : : const struct ftl_mngt_process_desc *pdesc, void *init_ctx)
163 : : {
164 : 255 : int rc = 0;
165 : :
166 [ + + - + : 255 : if (init_ctx || pdesc->init_handler) {
# # # # ]
167 [ - + # # ]: 8 : ftl_bug(!init_ctx);
168 [ - + # # : 8 : ftl_bug(!pdesc->init_handler);
# # # # ]
169 [ # # # # : 8 : rc = pdesc->init_handler(dev, mngt, init_ctx);
# # # # ]
170 : 0 : }
171 : :
172 : 255 : return rc;
173 : : }
174 : :
175 : : static int
176 : 255 : _ftl_mngt_process_execute(struct spdk_ftl_dev *dev, const struct ftl_mngt_process_desc *pdesc,
177 : : ftl_mngt_completion cb, void *cb_ctx, bool silent, void *init_ctx)
178 : : {
179 : : const struct ftl_mngt_step_desc *sdesc;
180 : : struct ftl_mngt_process *mngt;
181 : 255 : int rc = 0;
182 : :
183 [ # # ]: 255 : mngt = allocate_mngt(dev, pdesc, cb, cb_ctx, silent);
184 [ - + ]: 255 : if (!mngt) {
185 : 0 : rc = -ENOMEM;
186 : 0 : goto error;
187 : : }
188 : :
189 [ + + # # : 255 : if (pdesc->error_handler) {
# # ]
190 : : /* Initialize a step for error handler */
191 [ # # # # : 23 : mngt->cleanup.step.desc = &mngt->cleanup.desc;
# # # # #
# # # ]
192 [ # # # # : 23 : mngt->cleanup.desc.name = "Handle ERROR";
# # # # ]
193 [ # # # # : 23 : mngt->cleanup.desc.cleanup = pdesc->error_handler;
# # # # #
# # # ]
194 : :
195 : : /* Queue error handler to the rollback queue, it will be executed at the end */
196 [ - + # # : 23 : TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, &mngt->cleanup.step,
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
197 : : rollback.entry);
198 : 0 : }
199 : :
200 : : /* Initialize steps */
201 [ # # # # : 255 : sdesc = mngt->desc->steps;
# # ]
202 [ + + # # : 1841 : while (sdesc->action) {
# # ]
203 : 1586 : rc = init_step(mngt, sdesc);
204 [ - + ]: 1586 : if (rc) {
205 : 0 : goto error;
206 : : }
207 [ # # ]: 1586 : sdesc++;
208 : : }
209 : :
210 : 255 : rc = invoke_init_handler(dev, mngt, pdesc, init_ctx);
211 [ + + ]: 255 : if (rc) {
212 : 3 : goto error;
213 : : }
214 : :
215 : 252 : action_execute(mngt);
216 : 252 : return 0;
217 : 3 : error:
218 : 3 : free_mngt(mngt);
219 : 3 : return rc;
220 : 0 : }
221 : :
222 : : int
223 : 87 : ftl_mngt_process_execute(struct spdk_ftl_dev *dev, const struct ftl_mngt_process_desc *pdesc,
224 : : ftl_mngt_completion cb, void *cb_ctx)
225 : : {
226 : 87 : return _ftl_mngt_process_execute(dev, pdesc, cb, cb_ctx, false, NULL);
227 : : }
228 : :
229 : : int
230 : 45 : ftl_mngt_process_rollback(struct spdk_ftl_dev *dev, const struct ftl_mngt_process_desc *pdesc,
231 : : ftl_mngt_completion cb, void *cb_ctx)
232 : : {
233 : : const struct ftl_mngt_step_desc *sdesc;
234 : : struct ftl_mngt_process *mngt;
235 : 45 : int rc = 0;
236 : :
237 : 45 : mngt = allocate_mngt(dev, pdesc, cb, cb_ctx, true);
238 [ - + ]: 45 : if (!mngt) {
239 : 0 : rc = -ENOMEM;
240 : 0 : goto error;
241 : : }
242 : :
243 : : /* Initialize steps for rollback */
244 [ # # # # : 45 : sdesc = mngt->desc->steps;
# # ]
245 [ + + # # : 654 : while (sdesc->action) {
# # ]
246 [ + + # # : 609 : if (!sdesc->cleanup) {
# # ]
247 [ # # ]: 219 : sdesc++;
248 : 219 : continue;
249 : : }
250 : 390 : rc = init_step(mngt, sdesc);
251 [ - + ]: 390 : if (rc) {
252 : 0 : goto error;
253 : : }
254 [ # # ]: 390 : sdesc++;
255 : : }
256 : :
257 : : /* Build rollback list */
258 : : struct ftl_mngt_step *step;
259 [ + + # # : 435 : TAILQ_FOREACH(step, &mngt->action_queue_todo, action.entry) {
# # # # #
# # # # #
# # ]
260 [ # # # # : 390 : step->action.silent = true;
# # ]
261 [ + + # # : 390 : TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, step,
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
262 : : rollback.entry);
263 : 0 : }
264 : :
265 [ # # # # ]: 45 : mngt->rollback = true;
266 : 45 : rollback_execute(mngt);
267 : 45 : return 0;
268 : 0 : error:
269 : 0 : free_mngt(mngt);
270 : 0 : return rc;
271 : 0 : }
272 : :
273 : : struct spdk_ftl_dev *
274 : 2162 : ftl_mngt_get_dev(struct ftl_mngt_process *mngt)
275 : : {
276 [ # # # # ]: 2162 : return mngt->dev;
277 : : }
278 : :
279 : : int
280 : 36 : ftl_mngt_alloc_step_ctx(struct ftl_mngt_process *mngt, size_t size)
281 : : {
282 : 36 : struct ftl_mngt_step *step = get_current_step(mngt);
283 : 36 : void *arg = calloc(1, size);
284 : :
285 [ - + ]: 36 : if (!arg) {
286 : 0 : return -ENOMEM;
287 : : }
288 : :
289 [ # # # # ]: 36 : free(step->ctx);
290 [ # # # # ]: 36 : step->ctx = arg;
291 : :
292 : 36 : return 0;
293 : 0 : }
294 : :
295 : : void *
296 : 1614 : ftl_mngt_get_step_ctx(struct ftl_mngt_process *mngt)
297 : : {
298 [ # # # # ]: 1614 : return get_current_step(mngt)->ctx;
299 : : }
300 : :
301 : : void *
302 : 4168 : ftl_mngt_get_process_ctx(struct ftl_mngt_process *mngt)
303 : : {
304 [ # # # # ]: 4168 : return mngt->ctx;
305 : : }
306 : :
307 : : void *
308 : 28 : ftl_mngt_get_caller_ctx(struct ftl_mngt_process *mngt)
309 : : {
310 [ # # # # : 28 : return mngt->caller.cb_ctx;
# # ]
311 : : }
312 : :
313 : : void
314 : 1967 : ftl_mngt_next_step(struct ftl_mngt_process *mngt)
315 : : {
316 [ - + + + : 1967 : if (false == mngt->rollback) {
# # # # ]
317 : 1562 : action_next(mngt);
318 : 0 : } else {
319 : 405 : rollback_next(mngt);
320 : : }
321 : 1967 : }
322 : :
323 : : void
324 : 59 : ftl_mngt_skip_step(struct ftl_mngt_process *mngt)
325 : : {
326 [ - + + + : 59 : if (mngt->rollback) {
# # # # ]
327 [ # # # # : 27 : get_current_step(mngt)->rollback.silent = true;
# # ]
328 : 0 : } else {
329 [ # # # # : 32 : get_current_step(mngt)->action.silent = true;
# # ]
330 : : }
331 : 59 : ftl_mngt_next_step(mngt);
332 : 59 : }
333 : :
334 : : void
335 : 277236 : ftl_mngt_continue_step(struct ftl_mngt_process *mngt)
336 : : {
337 : :
338 [ - + + - : 277236 : if (!mngt->continuing) {
# # # # ]
339 [ - + + + : 277236 : if (false == mngt->rollback) {
# # # # ]
340 : 277224 : action_execute(mngt);
341 : 0 : } else {
342 : 12 : rollback_execute(mngt);
343 : : }
344 : 0 : }
345 : :
346 [ # # # # ]: 277236 : mngt->continuing = true;
347 : 277236 : }
348 : :
349 : : static void
350 : 198 : child_cb(struct spdk_ftl_dev *dev, void *ctx, int status)
351 : : {
352 : 198 : struct ftl_mngt_process *parent = ctx;
353 : :
354 [ + + ]: 198 : if (status) {
355 : 3 : ftl_mngt_fail_step(parent);
356 : 0 : } else {
357 : 195 : ftl_mngt_next_step(parent);
358 : : }
359 : 198 : }
360 : :
361 : : void
362 : 168 : ftl_mngt_call_process(struct ftl_mngt_process *mngt,
363 : : const struct ftl_mngt_process_desc *pdesc,
364 : : void *init_ctx)
365 : : {
366 [ + + # # : 168 : if (_ftl_mngt_process_execute(mngt->dev, pdesc, child_cb, mngt, true, init_ctx)) {
# # ]
367 : 3 : ftl_mngt_fail_step(mngt);
368 : 0 : } else {
369 [ - + + + : 165 : if (mngt->rollback) {
# # # # ]
370 [ # # # # : 3 : get_current_step(mngt)->rollback.silent = true;
# # ]
371 : 0 : } else {
372 [ # # # # : 162 : get_current_step(mngt)->action.silent = true;
# # ]
373 : : }
374 : : }
375 : 168 : }
376 : :
377 : : void
378 : 33 : ftl_mngt_call_process_rollback(struct ftl_mngt_process *mngt,
379 : : const struct ftl_mngt_process_desc *pdesc)
380 : : {
381 [ - + # # : 33 : if (ftl_mngt_process_rollback(mngt->dev, pdesc, child_cb, mngt)) {
# # ]
382 : 0 : ftl_mngt_fail_step(mngt);
383 : 0 : } else {
384 [ - + + + : 33 : if (mngt->rollback) {
# # # # ]
385 [ # # # # : 3 : get_current_step(mngt)->rollback.silent = true;
# # ]
386 : 0 : } else {
387 [ # # # # : 30 : get_current_step(mngt)->action.silent = true;
# # ]
388 : : }
389 : : }
390 : 33 : }
391 : :
392 : : void
393 : 12 : ftl_mngt_fail_step(struct ftl_mngt_process *mngt)
394 : : {
395 [ # # # # ]: 12 : mngt->status = -1;
396 : :
397 [ - + + - : 12 : if (false == mngt->rollback) {
# # # # ]
398 : 12 : action_done(mngt, -1);
399 : 0 : } else {
400 : 0 : rollback_done(mngt, -1);
401 : : }
402 : :
403 [ # # # # ]: 12 : mngt->rollback = true;
404 : 12 : rollback_execute(mngt);
405 : 12 : }
406 : :
407 : : static inline float
408 : 1809 : tsc_to_ms(uint64_t tsc)
409 : : {
410 : 1809 : float ms = tsc;
411 : 1809 : ms /= (float)spdk_get_ticks_hz();
412 : 1809 : ms *= 1000.0;
413 : 1809 : return ms;
414 : : }
415 : :
416 : : static void
417 : 1979 : trace_step(struct spdk_ftl_dev *dev, struct ftl_mngt_step *step, bool rollback)
418 : : {
419 : : uint64_t duration;
420 [ + + ]: 1979 : const char *what = rollback ? "Rollback" : "Action";
421 [ + + # # : 1979 : int silent = rollback ? step->rollback.silent : step->action.silent;
# # # # #
# # # # #
# # ]
422 : :
423 [ + + ]: 1979 : if (silent) {
424 : 257 : return;
425 : : }
426 : :
427 [ + - # # : 1722 : FTL_NOTICELOG(dev, "%s\n", what);
# # # # ]
428 [ + - # # : 1722 : FTL_NOTICELOG(dev, "\t name: %s\n", step->desc->name);
# # # # #
# # # # #
# # ]
429 [ # # # # : 1722 : duration = step->action.stop - step->action.start;
# # # # #
# # # ]
430 [ + - # # : 1722 : FTL_NOTICELOG(dev, "\t duration: %.3f ms\n", tsc_to_ms(duration));
# # # # ]
431 [ + - # # : 1722 : FTL_NOTICELOG(dev, "\t status: %d\n", step->action.status);
# # # # #
# # # #
# ]
432 : 0 : }
433 : :
434 : : static void
435 : 297 : finish_msg(void *ctx)
436 : : {
437 : 297 : struct ftl_mngt_process *mngt = ctx;
438 : 297 : char *devname = NULL;
439 : :
440 [ - + + + : 297 : if (!mngt->silent && mngt->dev->conf.name) {
+ + # # #
# # # # #
# # # # #
# ]
441 : : /* the callback below can free the device so make a temp copy of the name */
442 [ - + # # : 63 : devname = strdup(mngt->dev->conf.name);
# # # # #
# # # ]
443 : 0 : }
444 : :
445 [ # # # # : 297 : mngt->caller.cb(mngt->dev, mngt->caller.cb_ctx, mngt->status);
# # # # #
# # # # #
# # # # #
# # # #
# ]
446 : :
447 [ + + # # : 297 : if (mngt->desc->deinit_handler) {
# # # # #
# ]
448 [ # # # # : 5 : mngt->desc->deinit_handler(mngt->dev, mngt);
# # # # #
# # # # #
# # ]
449 : 0 : }
450 : :
451 [ - + + + : 297 : if (!mngt->silent) {
# # # # ]
452 : : /* TODO: refactor the logging macros to pass just the name instead of device */
453 : 87 : struct spdk_ftl_dev tmpdev = {
454 : 0 : .conf = {
455 : 0 : .name = devname
456 : : }
457 : : };
458 : :
459 [ # # # # : 87 : FTL_NOTICELOG(&tmpdev, "Management process finished, name '%s', duration = %.3f ms, result %d\n",
# # # # #
# # # # #
# # # # #
# ]
460 : : mngt->desc->name,
461 : : tsc_to_ms(mngt->tsc_stop - mngt->tsc_start),
462 : : mngt->status);
463 : 0 : }
464 : 297 : free_mngt(mngt);
465 : 297 : free(devname);
466 : 297 : }
467 : :
468 : : void
469 : 297 : ftl_mngt_finish(struct ftl_mngt_process *mngt)
470 : : {
471 [ # # # # ]: 297 : mngt->tsc_stop = spdk_get_ticks();
472 [ # # # # : 297 : spdk_thread_send_msg(mngt->caller.thread, finish_msg, mngt);
# # ]
473 : 297 : }
474 : :
475 : : /*
476 : : * Actions
477 : : */
478 : : static void
479 : 1562 : action_next(struct ftl_mngt_process *mngt)
480 : : {
481 [ - + # # : 1562 : if (TAILQ_EMPTY(&mngt->action_queue_todo)) {
# # # # ]
482 : : /* Nothing to do, finish the management process */
483 : 0 : ftl_mngt_finish(mngt);
484 : 0 : return;
485 : : } else {
486 : 1562 : action_done(mngt, 0);
487 : 1562 : action_execute(mngt);
488 : : }
489 : 0 : }
490 : :
491 : : static void
492 : 279038 : action_msg(void *ctx)
493 : : {
494 : 279038 : struct ftl_mngt_process *mngt = ctx;
495 : : struct ftl_mngt_step *step;
496 : :
497 [ # # # # ]: 279038 : mngt->continuing = false;
498 : :
499 [ + + # # : 279038 : if (TAILQ_EMPTY(&mngt->action_queue_todo)) {
# # # # ]
500 : 240 : ftl_mngt_finish(mngt);
501 : 240 : return;
502 : : }
503 : :
504 [ # # # # : 278798 : step = TAILQ_FIRST(&mngt->action_queue_todo);
# # ]
505 [ + + # # : 278798 : if (!step->action.start) {
# # # # ]
506 [ # # # # : 1586 : step->action.start = spdk_get_ticks();
# # ]
507 : 0 : }
508 [ # # # # : 278798 : step->desc->action(mngt->dev, mngt);
# # # # #
# # # # #
# # ]
509 : 0 : }
510 : :
511 : : static void
512 : 279038 : action_execute(struct ftl_mngt_process *mngt)
513 : : {
514 [ # # # # : 279038 : spdk_thread_send_msg(mngt->dev->core_thread, action_msg, mngt);
# # # # ]
515 : 279038 : }
516 : :
517 : : static void
518 : 1574 : action_done(struct ftl_mngt_process *mngt, int status)
519 : : {
520 : : struct ftl_mngt_step *step;
521 : :
522 [ - + # # : 1574 : assert(!TAILQ_EMPTY(&mngt->action_queue_todo));
# # # # #
# ]
523 [ # # # # : 1574 : step = TAILQ_FIRST(&mngt->action_queue_todo);
# # ]
524 [ + + # # : 1574 : TAILQ_REMOVE(&mngt->action_queue_todo, step, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
525 : :
526 [ # # # # : 1574 : TAILQ_INSERT_TAIL(&mngt->action_queue_done, step, action.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
527 [ + + # # : 1574 : if (step->desc->cleanup) {
# # # # #
# ]
528 [ + + # # : 495 : TAILQ_INSERT_HEAD(&mngt->rollback_queue_todo, step,
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
529 : : rollback.entry);
530 : 0 : }
531 : :
532 [ # # # # : 1574 : step->action.stop = spdk_get_ticks();
# # ]
533 [ # # # # : 1574 : step->action.status = status;
# # ]
534 : :
535 [ # # # # ]: 1574 : trace_step(mngt->dev, step, false);
536 : 1574 : }
537 : :
538 : : /*
539 : : * Rollback
540 : : */
541 : : static void
542 : 405 : rollback_next(struct ftl_mngt_process *mngt)
543 : : {
544 [ - + # # : 405 : if (TAILQ_EMPTY(&mngt->rollback_queue_todo)) {
# # # # ]
545 : : /* Nothing to do, finish the management process */
546 : 0 : ftl_mngt_finish(mngt);
547 : 0 : return;
548 : : } else {
549 : 405 : rollback_done(mngt, 0);
550 : 405 : rollback_execute(mngt);
551 : : }
552 : 0 : }
553 : :
554 : : static void
555 : 474 : rollback_msg(void *ctx)
556 : : {
557 : 474 : struct ftl_mngt_process *mngt = ctx;
558 : : struct ftl_mngt_step *step;
559 : :
560 [ # # # # ]: 474 : mngt->continuing = false;
561 : :
562 [ + + # # : 474 : if (TAILQ_EMPTY(&mngt->rollback_queue_todo)) {
# # # # ]
563 : 57 : ftl_mngt_finish(mngt);
564 : 57 : return;
565 : : }
566 : :
567 [ # # # # : 417 : step = TAILQ_FIRST(&mngt->rollback_queue_todo);
# # ]
568 [ + - # # : 417 : if (!step->rollback.start) {
# # # # ]
569 [ # # # # : 417 : step->rollback.start = spdk_get_ticks();
# # ]
570 : 0 : }
571 [ # # # # : 417 : step->desc->cleanup(mngt->dev, mngt);
# # # # #
# # # # #
# # ]
572 : 0 : }
573 : :
574 : : static void
575 : 474 : rollback_execute(struct ftl_mngt_process *mngt)
576 : : {
577 [ # # # # : 474 : spdk_thread_send_msg(mngt->dev->core_thread, rollback_msg, mngt);
# # # # ]
578 : 474 : }
579 : :
580 : : void
581 : 405 : rollback_done(struct ftl_mngt_process *mngt, int status)
582 : : {
583 : : struct ftl_mngt_step *step;
584 : :
585 [ - + # # : 405 : assert(!TAILQ_EMPTY(&mngt->rollback_queue_todo));
# # # # #
# ]
586 [ # # # # : 405 : step = TAILQ_FIRST(&mngt->rollback_queue_todo);
# # ]
587 [ + + # # : 405 : TAILQ_REMOVE(&mngt->rollback_queue_todo, step, rollback.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
588 [ # # # # : 405 : TAILQ_INSERT_TAIL(&mngt->rollback_queue_done, step, rollback.entry);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
589 : :
590 [ # # # # : 405 : step->rollback.stop = spdk_get_ticks();
# # ]
591 [ # # # # : 405 : step->rollback.status = status;
# # ]
592 : :
593 [ # # # # ]: 405 : trace_step(mngt->dev, step, true);
594 : 405 : }
|