Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "ftl_band.h"
7 : : #include "ftl_core.h"
8 : : #include "ftl_debug.h"
9 : : #include "ftl_io.h"
10 : : #include "ftl_internal.h"
11 : : #include "spdk/ftl.h"
12 : : #include "spdk/likely.h"
13 : :
14 : : struct ftl_reloc;
15 : : struct ftl_band_reloc;
16 : :
17 : : /* TODO: Should probably change the move naming nomenclature to something more descriptive */
18 : : enum ftl_reloc_move_state {
19 : : FTL_RELOC_STATE_READ = 0,
20 : : FTL_RELOC_STATE_PIN,
21 : : FTL_RELOC_STATE_WRITE,
22 : : FTL_RELOC_STATE_WAIT,
23 : : FTL_RELOC_STATE_HALT,
24 : :
25 : : FTL_RELOC_STATE_MAX
26 : : };
27 : :
28 : : struct ftl_reloc_move {
29 : : /* FTL device */
30 : : struct spdk_ftl_dev *dev;
31 : :
32 : : struct ftl_reloc *reloc;
33 : :
34 : : /* Request for doing IO */
35 : : struct ftl_rq *rq;
36 : :
37 : : /* Move state (read, write) */
38 : : enum ftl_reloc_move_state state;
39 : :
40 : : /* Entry of circular list */
41 : : TAILQ_ENTRY(ftl_reloc_move) qentry;
42 : : };
43 : :
44 : : struct ftl_reloc {
45 : : /* Device associated with relocate */
46 : : struct spdk_ftl_dev *dev;
47 : :
48 : : /* Indicates relocate is about to halt */
49 : : bool halt;
50 : :
51 : : /* Band which are read to relocate */
52 : : struct ftl_band *band;
53 : :
54 : : /* Bands already read, but waiting for finishing GC */
55 : : TAILQ_HEAD(, ftl_band) band_done;
56 : : size_t band_done_count;
57 : :
58 : : /* Flags indicating reloc is waiting for a new band */
59 : : bool band_waiting;
60 : :
61 : : /* Maximum number of IOs per band */
62 : : size_t max_qdepth;
63 : :
64 : : /* Queue of free move objects */
65 : : struct ftl_reloc_move *move_buffer;
66 : :
67 : : /* Array of movers queue for each state */
68 : : TAILQ_HEAD(, ftl_reloc_move) move_queue[FTL_RELOC_STATE_MAX];
69 : :
70 : : };
71 : :
72 : : static void move_read_cb(struct ftl_rq *rq);
73 : : static void move_write_cb(struct ftl_rq *rq);
74 : : static void move_set_state(struct ftl_reloc_move *mv, enum ftl_reloc_move_state state);
75 : : static void move_write(struct ftl_reloc *reloc, struct ftl_reloc_move *mv);
76 : : static void move_read_error_cb(struct ftl_rq *rq, struct ftl_band *band, uint64_t idx,
77 : : uint64_t count);
78 : :
79 : : static void
80 : 432 : move_deinit(struct ftl_reloc_move *mv)
81 : : {
82 [ - + ]: 432 : assert(mv);
83 : 432 : ftl_rq_del(mv->rq);
84 : 432 : }
85 : :
86 : : static int
87 : 432 : move_init(struct ftl_reloc *reloc, struct ftl_reloc_move *mv)
88 : : {
89 : 432 : mv->state = FTL_RELOC_STATE_HALT;
90 : 432 : TAILQ_INSERT_TAIL(&reloc->move_queue[FTL_RELOC_STATE_HALT], mv, qentry);
91 : :
92 : 432 : mv->reloc = reloc;
93 : 432 : mv->dev = reloc->dev;
94 : 432 : mv->rq = ftl_rq_new(mv->dev, mv->dev->md_size);
95 : :
96 [ - + ]: 432 : if (!mv->rq) {
97 : 0 : return -ENOMEM;
98 : : }
99 : 432 : mv->rq->owner.priv = mv;
100 : :
101 : 432 : return 0;
102 : : }
103 : :
104 : : struct ftl_reloc *
105 : 27 : ftl_reloc_init(struct spdk_ftl_dev *dev)
106 : : {
107 : : struct ftl_reloc *reloc;
108 : : struct ftl_reloc_move *move;
109 : : size_t i, count;
110 : :
111 : 27 : reloc = calloc(1, sizeof(*reloc));
112 [ - + ]: 27 : if (!reloc) {
113 : 0 : return NULL;
114 : : }
115 : :
116 : 27 : reloc->dev = dev;
117 : 27 : reloc->halt = true;
118 : 27 : reloc->max_qdepth = dev->sb->max_reloc_qdepth;
119 : :
120 : 27 : reloc->move_buffer = calloc(reloc->max_qdepth, sizeof(*reloc->move_buffer));
121 [ - + ]: 27 : if (!reloc->move_buffer) {
122 [ # # ]: 0 : FTL_ERRLOG(dev, "Failed to initialize reloc moves pool");
123 : 0 : goto error;
124 : : }
125 : :
126 : : /* Initialize movers queues */
127 : 27 : count = SPDK_COUNTOF(reloc->move_queue);
128 [ + + ]: 162 : for (i = 0; i < count; ++i) {
129 : 135 : TAILQ_INIT(&reloc->move_queue[i]);
130 : : }
131 : :
132 [ + + ]: 459 : for (i = 0; i < reloc->max_qdepth; ++i) {
133 : 432 : move = &reloc->move_buffer[i];
134 : :
135 [ - + ]: 432 : if (move_init(reloc, move)) {
136 : 0 : goto error;
137 : : }
138 : : }
139 : :
140 : 27 : TAILQ_INIT(&reloc->band_done);
141 : :
142 : 27 : return reloc;
143 : 0 : error:
144 : 0 : ftl_reloc_free(reloc);
145 : 0 : return NULL;
146 : : }
147 : :
148 : : struct ftl_reloc_task_fini {
149 : : struct ftl_reloc_task *task;
150 : : spdk_msg_fn cb;
151 : : void *cb_arg;
152 : : };
153 : :
154 : : void
155 : 27 : ftl_reloc_free(struct ftl_reloc *reloc)
156 : : {
157 : : size_t i;
158 : :
159 [ - + ]: 27 : if (!reloc) {
160 : 0 : return;
161 : : }
162 : :
163 [ + - ]: 27 : if (reloc->move_buffer) {
164 [ + + ]: 459 : for (i = 0; i < reloc->max_qdepth; ++i) {
165 : 432 : move_deinit(&reloc->move_buffer[i]);
166 : : }
167 : : }
168 : :
169 : 27 : free(reloc->move_buffer);
170 : 27 : free(reloc);
171 : : }
172 : :
173 : : void
174 : 417 : ftl_reloc_halt(struct ftl_reloc *reloc)
175 : : {
176 : 417 : struct spdk_ftl_dev *dev = reloc->dev;
177 : :
178 [ - + + + : 417 : if (dev->conf.prep_upgrade_on_shutdown && 0 == dev->num_free) {
- + ]
179 : : /*
180 : : * In shutdown upgrade procedure, it is required to have
181 : : * at least one free band. Keep reloc running to reclaim
182 : : * the band.
183 : : */
184 : 0 : return;
185 : : }
186 : :
187 : 417 : reloc->halt = true;
188 : : }
189 : :
190 : : void
191 : 27 : ftl_reloc_resume(struct ftl_reloc *reloc)
192 : : {
193 : : struct ftl_reloc_move *mv, *next;
194 : 27 : reloc->halt = false;
195 : :
196 [ + + ]: 459 : TAILQ_FOREACH_SAFE(mv, &reloc->move_queue[FTL_RELOC_STATE_HALT], qentry,
197 : : next) {
198 : 432 : move_set_state(mv, FTL_RELOC_STATE_READ);
199 : : }
200 : 27 : }
201 : :
202 : : static void
203 : 864 : move_set_state(struct ftl_reloc_move *mv, enum ftl_reloc_move_state state)
204 : : {
205 : 864 : struct ftl_reloc *reloc = mv->reloc;
206 : :
207 [ + - + - ]: 864 : switch (state) {
208 : 432 : case FTL_RELOC_STATE_READ:
209 : 432 : mv->rq->owner.cb = move_read_cb;
210 : 432 : mv->rq->owner.error = move_read_error_cb;
211 : 432 : mv->rq->iter.idx = 0;
212 : 432 : mv->rq->iter.count = 0;
213 : 432 : mv->rq->success = true;
214 : 432 : break;
215 : :
216 : 0 : case FTL_RELOC_STATE_WRITE:
217 : 0 : mv->rq->owner.cb = move_write_cb;
218 : 0 : mv->rq->owner.error = NULL;
219 : 0 : break;
220 : :
221 : 432 : case FTL_RELOC_STATE_PIN:
222 : : case FTL_RELOC_STATE_WAIT:
223 : : case FTL_RELOC_STATE_HALT:
224 : 432 : break;
225 : :
226 : 0 : default:
227 : 0 : ftl_abort();
228 : : break;
229 : : }
230 : :
231 [ + - ]: 864 : if (mv->state != state) {
232 : : /* Remove the mover from previous queue */
233 [ + + ]: 864 : TAILQ_REMOVE(&reloc->move_queue[mv->state], mv, qentry);
234 : : /* Insert the mover to the new queue */
235 : 864 : TAILQ_INSERT_TAIL(&reloc->move_queue[state], mv, qentry);
236 : : /* Update state */
237 : 864 : mv->state = state;
238 : : }
239 : 864 : }
240 : :
241 : : static void
242 : 0 : move_get_band_cb(struct ftl_band *band, void *cntx, bool status)
243 : : {
244 : 0 : struct ftl_reloc *reloc = cntx;
245 : :
246 [ # # ]: 0 : if (spdk_likely(status)) {
247 : 0 : reloc->band = band;
248 : 0 : ftl_band_iter_init(band);
249 : : }
250 : 0 : reloc->band_waiting = false;
251 : 0 : }
252 : :
253 : : static void
254 : 27306330 : move_grab_new_band(struct ftl_reloc *reloc)
255 : : {
256 [ - + + - ]: 27306330 : if (!reloc->band_waiting) {
257 [ + - ]: 27306330 : if (!ftl_needs_reloc(reloc->dev)) {
258 : 27306330 : return;
259 : : }
260 : :
261 : : /* Limit number of simultaneously relocated bands */
262 [ # # ]: 0 : if (reloc->band_done_count > 2) {
263 : 0 : return;
264 : : }
265 : :
266 : 0 : reloc->band_waiting = true;
267 : 0 : ftl_band_get_next_gc(reloc->dev, move_get_band_cb, reloc);
268 : : }
269 : : }
270 : :
271 : : static struct ftl_band *
272 : 27306330 : move_get_band(struct ftl_reloc *reloc)
273 : : {
274 : 27306330 : struct ftl_band *band = reloc->band;
275 : :
276 [ + - ]: 27306330 : if (!band) {
277 : 27306330 : move_grab_new_band(reloc);
278 : 27306330 : return NULL;
279 : : }
280 : :
281 [ # # ]: 0 : if (!ftl_band_filled(band, band->md->iter.offset)) {
282 : : /* Band still not read, we can continue reading */
283 : 0 : return band;
284 : : }
285 : :
286 : 0 : TAILQ_INSERT_TAIL(&reloc->band_done, band, queue_entry);
287 : 0 : reloc->band_done_count++;
288 : 0 : reloc->band = NULL;
289 : :
290 : 0 : return NULL;
291 : : }
292 : :
293 : : static void
294 : 0 : move_advance_rq(struct ftl_rq *rq)
295 : : {
296 : 0 : struct ftl_band *band = rq->io.band;
297 : : uint64_t offset, i;
298 : 0 : struct ftl_rq_entry *entry = &rq->entries[rq->iter.idx];
299 : :
300 [ # # ]: 0 : assert(rq->iter.idx + rq->iter.count <= rq->num_blocks);
301 : :
302 [ # # ]: 0 : for (i = 0; i < rq->iter.count; i++) {
303 : 0 : offset = ftl_band_block_offset_from_addr(band, rq->io.addr);
304 : :
305 [ # # ]: 0 : assert(offset < ftl_get_num_blocks_in_band(band->dev));
306 [ # # ]: 0 : assert(ftl_band_block_offset_valid(band, offset));
307 : :
308 : 0 : entry->lba = band->p2l_map.band_map[offset].lba;
309 : 0 : entry->addr = rq->io.addr;
310 : 0 : entry->owner.priv = band;
311 : 0 : entry->seq_id = band->p2l_map.band_map[offset].seq_id;
312 : :
313 : 0 : entry++;
314 : 0 : rq->io.addr = ftl_band_next_addr(band, rq->io.addr, 1);
315 : 0 : band->owner.cnt++;
316 : : }
317 : :
318 : : /* Increase QD for the request */
319 : 0 : rq->iter.qd++;
320 : :
321 : : /* Advanced request iterator */
322 : 0 : rq->iter.idx += rq->iter.count;
323 : 0 : }
324 : :
325 : : static void
326 : 0 : move_init_entries(struct ftl_rq *rq, uint64_t idx, uint64_t count)
327 : : {
328 : 0 : uint64_t i = 0;
329 : 0 : struct ftl_rq_entry *iter = &rq->entries[idx];
330 : :
331 [ # # ]: 0 : assert(idx + count <= rq->num_blocks);
332 : :
333 : 0 : i = 0;
334 [ # # ]: 0 : while (i < count) {
335 : 0 : iter->addr = FTL_ADDR_INVALID;
336 : 0 : iter->owner.priv = NULL;
337 : 0 : iter->lba = FTL_LBA_INVALID;
338 : 0 : iter->seq_id = 0;
339 : 0 : iter++;
340 : 0 : i++;
341 : : }
342 : 0 : }
343 : :
344 : : static void
345 : 0 : move_read_error_cb(struct ftl_rq *rq, struct ftl_band *band, uint64_t idx, uint64_t count)
346 : : {
347 : 0 : move_init_entries(rq, idx, count);
348 : 0 : band->owner.cnt -= count;
349 : 0 : }
350 : :
351 : : static void
352 : 0 : move_read_cb(struct ftl_rq *rq)
353 : : {
354 : 0 : struct ftl_reloc_move *mv = rq->owner.priv;
355 : :
356 : : /* Decrease QD of the request */
357 [ # # ]: 0 : assert(rq->iter.qd > 0);
358 : 0 : rq->iter.qd--;
359 : :
360 [ # # # # ]: 0 : if (rq->iter.idx != rq->num_blocks || rq->iter.qd) {
361 : 0 : return;
362 : : }
363 : :
364 : 0 : move_set_state(mv, FTL_RELOC_STATE_PIN);
365 : : }
366 : :
367 : : static void
368 : 0 : move_rq_pad(struct ftl_rq *rq, struct ftl_band *band)
369 : : {
370 : 0 : struct ftl_rq_entry *entry = &rq->entries[rq->iter.idx];
371 : :
372 [ # # ]: 0 : for (; rq->iter.idx < rq->num_blocks; ++rq->iter.idx) {
373 : 0 : entry->addr = rq->io.addr;
374 : 0 : entry->owner.priv = band;
375 : 0 : entry->lba = FTL_LBA_INVALID;
376 : 0 : entry->seq_id = 0;
377 : 0 : entry++;
378 : 0 : rq->io.addr = ftl_band_next_addr(band, rq->io.addr, 1);
379 : 0 : band->owner.cnt++;
380 : : }
381 : :
382 [ # # ]: 0 : assert(rq->iter.idx == rq->num_blocks);
383 : 0 : }
384 : :
385 : : static void
386 : 0 : move_read(struct ftl_reloc *reloc, struct ftl_reloc_move *mv, struct ftl_band *band)
387 : : {
388 : 0 : struct ftl_rq *rq = mv->rq;
389 : 0 : uint64_t blocks = ftl_get_num_blocks_in_band(band->dev);
390 : 0 : uint64_t pos = band->md->iter.offset;
391 : 0 : uint64_t begin = ftl_bitmap_find_first_set(band->p2l_map.valid, pos, UINT64_MAX);
392 : : uint64_t end, band_left, rq_left;
393 : :
394 [ # # ]: 0 : if (spdk_likely(begin < blocks)) {
395 [ # # ]: 0 : if (begin > pos) {
396 : 0 : ftl_band_iter_advance(band, begin - pos);
397 [ # # ]: 0 : } else if (begin == pos) {
398 : : /* Valid block at the position of iterator */
399 : : } else {
400 : : /* Inconsistent state */
401 : 0 : ftl_abort();
402 : : }
403 [ # # ]: 0 : } else if (UINT64_MAX == begin) {
404 : : /* No more valid LBAs in the band */
405 : 0 : band_left = ftl_band_user_blocks_left(band, pos);
406 : 0 : ftl_band_iter_advance(band, band_left);
407 : :
408 [ # # ]: 0 : assert(ftl_band_filled(band, band->md->iter.offset));
409 : :
410 [ # # ]: 0 : if (rq->iter.idx) {
411 : 0 : move_rq_pad(rq, band);
412 : 0 : move_set_state(mv, FTL_RELOC_STATE_WAIT);
413 : 0 : rq->iter.qd++;
414 : 0 : rq->owner.cb(rq);
415 : : }
416 : :
417 : 0 : return;
418 : : } else {
419 : : /* Inconsistent state */
420 : 0 : ftl_abort();
421 : : }
422 : :
423 : 0 : rq_left = rq->num_blocks - rq->iter.idx;
424 [ # # ]: 0 : assert(rq_left > 0);
425 : :
426 : : /* Find next clear bit, but no further than max request count */
427 : 0 : end = ftl_bitmap_find_first_clear(band->p2l_map.valid, begin + 1, begin + rq_left);
428 [ # # ]: 0 : if (end != UINT64_MAX) {
429 : 0 : rq_left = end - begin;
430 : : }
431 : :
432 : 0 : band_left = ftl_band_user_blocks_left(band, band->md->iter.offset);
433 : 0 : rq->iter.count = spdk_min(rq_left, band_left);
434 : :
435 : 0 : ftl_band_rq_read(band, rq);
436 : :
437 : 0 : move_advance_rq(rq);
438 : :
439 : : /* Advance band iterator */
440 : 0 : ftl_band_iter_advance(band, rq->iter.count);
441 : :
442 : : /* If band is fully written pad rest of request */
443 [ # # ]: 0 : if (ftl_band_filled(band, band->md->iter.offset)) {
444 : 0 : move_rq_pad(rq, band);
445 : : }
446 : :
447 [ # # ]: 0 : if (rq->iter.idx == rq->num_blocks) {
448 : : /*
449 : : * All request entries scheduled for reading,
450 : : * We can change state to waiting
451 : : */
452 : 0 : move_set_state(mv, FTL_RELOC_STATE_WAIT);
453 : : }
454 : : }
455 : :
456 : : static void
457 : 0 : move_pin_cb(struct spdk_ftl_dev *dev, int status, struct ftl_l2p_pin_ctx *pin_ctx)
458 : : {
459 : 0 : struct ftl_reloc_move *mv = pin_ctx->cb_ctx;
460 : 0 : struct ftl_rq *rq = mv->rq;
461 : :
462 [ # # ]: 0 : if (status) {
463 : 0 : rq->iter.status = status;
464 : 0 : pin_ctx->lba = FTL_LBA_INVALID;
465 : : }
466 : :
467 [ # # ]: 0 : if (--rq->iter.remaining == 0) {
468 [ # # ]: 0 : if (rq->iter.status) {
469 : : /* unpin and try again */
470 : 0 : ftl_rq_unpin(rq);
471 : 0 : move_set_state(mv, FTL_RELOC_STATE_PIN);
472 : 0 : return;
473 : : }
474 : :
475 : 0 : move_set_state(mv, FTL_RELOC_STATE_WRITE);
476 : : }
477 : : }
478 : :
479 : : static void
480 : 0 : move_pin(struct ftl_reloc_move *mv)
481 : : {
482 : 0 : struct ftl_rq *rq = mv->rq;
483 : 0 : struct ftl_rq_entry *entry = rq->entries;
484 : : uint64_t i;
485 : :
486 : 0 : move_set_state(mv, FTL_RELOC_STATE_WAIT);
487 : :
488 : 0 : rq->iter.remaining = rq->iter.count = rq->num_blocks;
489 : 0 : rq->iter.status = 0;
490 : :
491 [ # # ]: 0 : for (i = 0; i < rq->num_blocks; i++) {
492 [ # # ]: 0 : if (entry->lba != FTL_LBA_INVALID) {
493 : 0 : ftl_l2p_pin(rq->dev, entry->lba, 1, move_pin_cb, mv, &entry->l2p_pin_ctx);
494 : : } else {
495 : 0 : ftl_l2p_pin_skip(rq->dev, move_pin_cb, mv, &entry->l2p_pin_ctx);
496 : : }
497 : 0 : entry++;
498 : : }
499 : 0 : }
500 : :
501 : : static void
502 : 0 : move_finish_write(struct ftl_rq *rq)
503 : : {
504 : : uint64_t i;
505 : 0 : struct spdk_ftl_dev *dev = rq->dev;
506 : 0 : struct ftl_rq_entry *iter = rq->entries;
507 : 0 : ftl_addr addr = rq->io.addr;
508 : 0 : struct ftl_band *rq_band = rq->io.band;
509 : : struct ftl_band *band;
510 : :
511 [ # # ]: 0 : for (i = 0; i < rq->num_blocks; ++i, ++iter) {
512 : 0 : band = iter->owner.priv;
513 : :
514 [ # # ]: 0 : if (band) {
515 [ # # ]: 0 : assert(band->owner.cnt > 0);
516 : 0 : band->owner.cnt--;
517 : : }
518 [ # # ]: 0 : if (iter->lba != FTL_LBA_INVALID) {
519 : : /* Update L2P table */
520 : 0 : ftl_l2p_update_base(dev, iter->lba, addr, iter->addr);
521 : 0 : ftl_l2p_unpin(dev, iter->lba, 1);
522 : : }
523 : 0 : addr = ftl_band_next_addr(rq_band, addr, 1);
524 : : }
525 : 0 : }
526 : :
527 : : static void
528 : 0 : move_write_cb(struct ftl_rq *rq)
529 : : {
530 : 0 : struct ftl_reloc_move *mv = rq->owner.priv;
531 : :
532 [ # # ]: 0 : assert(rq->iter.qd == 1);
533 : 0 : rq->iter.qd--;
534 : :
535 [ # # # # ]: 0 : if (spdk_likely(rq->success)) {
536 : 0 : move_finish_write(rq);
537 : 0 : move_set_state(mv, FTL_RELOC_STATE_READ);
538 : : } else {
539 : : /* Write failed, repeat write */
540 : 0 : move_set_state(mv, FTL_RELOC_STATE_WRITE);
541 : : }
542 : 0 : }
543 : :
544 : : static void
545 : 0 : move_write(struct ftl_reloc *reloc, struct ftl_reloc_move *mv)
546 : : {
547 : 0 : struct spdk_ftl_dev *dev = mv->dev;
548 : 0 : struct ftl_rq *rq = mv->rq;
549 : :
550 [ # # ]: 0 : assert(rq->iter.idx == rq->num_blocks);
551 : :
552 : : /* Request contains data to be placed on a new location, submit it */
553 : 0 : ftl_writer_queue_rq(&dev->writer_gc, rq);
554 : 0 : rq->iter.qd++;
555 : :
556 : 0 : move_set_state(mv, FTL_RELOC_STATE_WAIT);
557 : 0 : }
558 : :
559 : : static void
560 : 27439513 : move_run(struct ftl_reloc *reloc, struct ftl_reloc_move *mv)
561 : : {
562 : : struct ftl_band *band;
563 : :
564 [ + - - + : 27439513 : switch (mv->state) {
- ]
565 : 27306762 : case FTL_RELOC_STATE_READ: {
566 [ - + + + ]: 27306762 : if (spdk_unlikely(reloc->halt)) {
567 : 432 : move_set_state(mv, FTL_RELOC_STATE_HALT);
568 : 432 : break;
569 : : }
570 : :
571 : 27306330 : band = move_get_band(reloc);
572 [ + - ]: 27306330 : if (!band) {
573 : 27306330 : break;
574 : : }
575 : :
576 : 0 : move_read(reloc, mv, band);
577 : : }
578 : 0 : break;
579 : :
580 : 0 : case FTL_RELOC_STATE_PIN:
581 : 0 : move_pin(mv);
582 : 0 : ftl_add_io_activity(reloc->dev);
583 : 0 : break;
584 : :
585 : 0 : case FTL_RELOC_STATE_WRITE:
586 [ # # # # ]: 0 : if (spdk_unlikely(reloc->halt)) {
587 : 0 : ftl_rq_unpin(mv->rq);
588 : 0 : move_set_state(mv, FTL_RELOC_STATE_HALT);
589 : 0 : break;
590 : : }
591 : :
592 : 0 : ftl_add_io_activity(reloc->dev);
593 : 0 : move_write(reloc, mv);
594 : 0 : break;
595 : :
596 : 132751 : case FTL_RELOC_STATE_HALT:
597 : : case FTL_RELOC_STATE_WAIT:
598 : 132751 : break;
599 : :
600 : 0 : default:
601 : 0 : assert(0);
602 : : ftl_abort();
603 : : break;
604 : : }
605 : 27439513 : }
606 : :
607 : : static void
608 : 0 : move_handle_band_error(struct ftl_band *band)
609 : : {
610 : 0 : struct ftl_reloc *reloc = band->dev->reloc;
611 : : /*
612 : : * Handle band error, it's because an error occurred during reading,
613 : : * Add band to the close band list, will try reloc it in a moment
614 : : */
615 [ # # ]: 0 : TAILQ_REMOVE(&reloc->band_done, band, queue_entry);
616 : 0 : reloc->band_done_count--;
617 : :
618 : 0 : band->md->state = FTL_BAND_STATE_CLOSING;
619 : 0 : ftl_band_set_state(band, FTL_BAND_STATE_CLOSED);
620 : 0 : }
621 : :
622 : : static void
623 : 27439081 : move_release_bands(struct ftl_reloc *reloc)
624 : : {
625 : : struct ftl_band *band;
626 : :
627 [ + - ]: 27439081 : if (TAILQ_EMPTY(&reloc->band_done)) {
628 : 27439081 : return;
629 : : }
630 : :
631 : 0 : band = TAILQ_FIRST(&reloc->band_done);
632 : :
633 [ # # # # ]: 0 : if (band->owner.cnt || ftl_band_qd(band)) {
634 : : /* Band still in use */
635 : 0 : return;
636 : : }
637 : :
638 [ # # ]: 0 : if (ftl_band_empty(band)) {
639 [ # # ]: 0 : assert(ftl_band_filled(band, band->md->iter.offset));
640 [ # # ]: 0 : TAILQ_REMOVE(&reloc->band_done, band, queue_entry);
641 : 0 : reloc->band_done_count--;
642 : 0 : ftl_band_free(band);
643 : : } else {
644 : 0 : move_handle_band_error(band);
645 : : }
646 : : }
647 : :
648 : : bool
649 : 1507 : ftl_reloc_is_halted(const struct ftl_reloc *reloc)
650 : : {
651 : : size_t i, count;
652 : :
653 : 1507 : count = SPDK_COUNTOF(reloc->move_queue);
654 [ + + ]: 6957 : for (i = 0; i < count; ++i) {
655 [ + + ]: 5867 : if (i == FTL_RELOC_STATE_HALT) {
656 : 1090 : continue;
657 : : }
658 : :
659 [ + + ]: 4777 : if (!TAILQ_EMPTY(&reloc->move_queue[i])) {
660 : 417 : return false;
661 : : }
662 : : }
663 : :
664 : 1090 : return true;
665 : : }
666 : :
667 : : void
668 : 27439081 : ftl_reloc(struct ftl_reloc *reloc)
669 : : {
670 : : size_t i, count;
671 : :
672 : 27439081 : count = SPDK_COUNTOF(reloc->move_queue);
673 [ + + ]: 164634486 : for (i = 0; i < count; ++i) {
674 [ + + ]: 137195405 : if (TAILQ_EMPTY(&reloc->move_queue[i])) {
675 : 109755892 : continue;
676 : : }
677 : :
678 : 27439513 : move_run(reloc, TAILQ_FIRST(&reloc->move_queue[i]));
679 : : }
680 : :
681 : 27439081 : move_release_bands(reloc);
682 : 27439081 : }
|