xref: /spdk/lib/ftl/ftl_reloc.c (revision 19d5c3ed8e87dbd240c77ae0ddb5eda25ae99b5f)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/likely.h"
35 #include "spdk_internal/log.h"
36 #include "spdk/ftl.h"
37 
38 #include "ftl_reloc.h"
39 #include "ftl_core.h"
40 #include "ftl_io.h"
41 #include "ftl_rwb.h"
42 #include "ftl_band.h"
43 #include "ftl_debug.h"
44 
45 /* Maximum active reloc moves */
46 #define FTL_RELOC_MAX_MOVES 256
47 
48 struct ftl_reloc;
49 struct ftl_band_reloc;
50 
51 enum ftl_reloc_move_state {
52 	FTL_RELOC_STATE_READ_LBA_MAP,
53 	FTL_RELOC_STATE_READ,
54 	FTL_RELOC_STATE_WRITE,
55 };
56 
57 enum ftl_band_reloc_state {
58 	FTL_BAND_RELOC_STATE_INACTIVE,
59 	FTL_BAND_RELOC_STATE_PENDING,
60 	FTL_BAND_RELOC_STATE_ACTIVE,
61 	FTL_BAND_RELOC_STATE_HIGH_PRIO
62 };
63 
64 struct ftl_reloc_move {
65 	struct ftl_band_reloc			*breloc;
66 
67 	/* Start addr */
68 	struct ftl_addr				addr;
69 
70 	/* Number of logical blocks */
71 	size_t					num_blocks;
72 
73 	/* Data buffer */
74 	void					*data;
75 
76 	/* Move state (read lba_map, read, write) */
77 	enum ftl_reloc_move_state		state;
78 
79 	/* IO associated with move */
80 	struct ftl_io				*io;
81 };
82 
83 struct ftl_band_reloc {
84 	struct ftl_reloc			*parent;
85 
86 	/* Band being relocated */
87 	struct ftl_band				*band;
88 
89 	/* Number of logical blocks to be relocated */
90 	size_t					num_blocks;
91 
92 	/* Bitmap of logical blocks to be relocated */
93 	struct spdk_bit_array			*reloc_map;
94 
95 	/*  State of the band reloc */
96 	enum ftl_band_reloc_state		state;
97 
98 	/* The band is being defragged */
99 	bool					defrag;
100 
101 	/* Reloc map iterator */
102 	struct {
103 		/* Array of zone offsets */
104 		size_t				*zone_offset;
105 
106 		/* Current zone */
107 		size_t				zone_current;
108 	} iter;
109 
110 	/* Number of outstanding moves */
111 	size_t					num_outstanding;
112 
113 	/* Pool of move objects */
114 	struct ftl_reloc_move			*moves;
115 
116 	/* Move queue */
117 	struct spdk_ring			*move_queue;
118 
119 	TAILQ_ENTRY(ftl_band_reloc)		entry;
120 };
121 
122 struct ftl_reloc {
123 	/* Device associated with relocate */
124 	struct spdk_ftl_dev			*dev;
125 
126 	/* Indicates relocate is about to halt */
127 	bool					halt;
128 
129 	/* Maximum number of IOs per band */
130 	size_t					max_qdepth;
131 
132 	/* Maximum number of active band relocates */
133 	size_t					max_active;
134 
135 	/* Maximum transfer size (in logical blocks) per single IO */
136 	size_t					xfer_size;
137 	/* Number of bands being defragged */
138 	size_t					num_defrag_bands;
139 
140 	/* Array of band relocates */
141 	struct ftl_band_reloc			*brelocs;
142 
143 	/* Number of active/priority band relocates */
144 	size_t					num_active;
145 
146 	/* Priority band relocates queue */
147 	TAILQ_HEAD(, ftl_band_reloc)		prio_queue;
148 
149 	/* Active band relocates queue */
150 	TAILQ_HEAD(, ftl_band_reloc)		active_queue;
151 
152 	/* Pending band relocates queue */
153 	TAILQ_HEAD(, ftl_band_reloc)		pending_queue;
154 };
155 
156 bool
157 ftl_reloc_is_defrag_active(const struct ftl_reloc *reloc)
158 {
159 	return reloc->num_defrag_bands > 0;
160 }
161 
162 static size_t
163 ftl_reloc_iter_zone_offset(struct ftl_band_reloc *breloc)
164 {
165 	size_t zone = breloc->iter.zone_current;
166 
167 	return breloc->iter.zone_offset[zone];
168 }
169 
170 static size_t
171 ftl_reloc_iter_zone_done(struct ftl_band_reloc *breloc)
172 {
173 	size_t num_blocks = ftl_get_num_blocks_in_zone(breloc->parent->dev);
174 
175 	return ftl_reloc_iter_zone_offset(breloc) == num_blocks;
176 }
177 
178 static void
179 ftl_reloc_clr_block(struct ftl_band_reloc *breloc, size_t block_off)
180 {
181 	if (!spdk_bit_array_get(breloc->reloc_map, block_off)) {
182 		return;
183 	}
184 
185 	spdk_bit_array_clear(breloc->reloc_map, block_off);
186 	assert(breloc->num_blocks);
187 	breloc->num_blocks--;
188 }
189 
190 static void
191 ftl_reloc_read_lba_map_cb(struct ftl_io *io, void *arg, int status)
192 {
193 	struct ftl_reloc_move *move = arg;
194 	struct ftl_band_reloc *breloc = move->breloc;
195 
196 	breloc->num_outstanding--;
197 	assert(status == 0);
198 	move->state = FTL_RELOC_STATE_WRITE;
199 	spdk_ring_enqueue(breloc->move_queue, (void **)&move, 1, NULL);
200 }
201 
202 static int
203 ftl_reloc_read_lba_map(struct ftl_band_reloc *breloc, struct ftl_reloc_move *move)
204 {
205 	struct ftl_band *band = breloc->band;
206 
207 	breloc->num_outstanding++;
208 	return ftl_band_read_lba_map(band, ftl_band_block_offset_from_addr(band, move->addr),
209 				     move->num_blocks, ftl_reloc_read_lba_map_cb, move);
210 }
211 
212 static void
213 ftl_reloc_prep(struct ftl_band_reloc *breloc)
214 {
215 	struct ftl_band *band = breloc->band;
216 	struct ftl_reloc *reloc = breloc->parent;
217 	struct ftl_reloc_move *move;
218 	size_t i;
219 
220 	reloc->num_active++;
221 
222 	if (!band->high_prio) {
223 		if (band->lba_map.ref_cnt == 0) {
224 			if (ftl_band_alloc_lba_map(band)) {
225 				assert(false);
226 			}
227 		} else {
228 			ftl_band_acquire_lba_map(band);
229 		}
230 	} else {
231 		ftl_band_acquire_lba_map(band);
232 	}
233 
234 	for (i = 0; i < reloc->max_qdepth; ++i) {
235 		move = &breloc->moves[i];
236 		move->state = FTL_RELOC_STATE_READ;
237 		spdk_ring_enqueue(breloc->move_queue, (void **)&move, 1, NULL);
238 	}
239 }
240 
241 static void
242 ftl_reloc_free_move(struct ftl_band_reloc *breloc, struct ftl_reloc_move *move)
243 {
244 	assert(move);
245 	spdk_dma_free(move->data);
246 	memset(move, 0, sizeof(*move));
247 	move->state = FTL_RELOC_STATE_READ;
248 	spdk_ring_enqueue(breloc->move_queue, (void **)&move, 1, NULL);
249 }
250 
251 static void
252 ftl_reloc_write_cb(struct ftl_io *io, void *arg, int status)
253 {
254 	struct ftl_reloc_move *move = arg;
255 	struct ftl_addr addr = move->addr;
256 	struct ftl_band_reloc *breloc = move->breloc;
257 	size_t i;
258 
259 	breloc->num_outstanding--;
260 
261 	if (status) {
262 		SPDK_ERRLOG("Reloc write failed with status: %d\n", status);
263 		assert(false);
264 		return;
265 	}
266 
267 	for (i = 0; i < move->num_blocks; ++i) {
268 		addr.offset = move->addr.offset + i;
269 		size_t block_off = ftl_band_block_offset_from_addr(breloc->band, addr);
270 		ftl_reloc_clr_block(breloc, block_off);
271 	}
272 
273 	ftl_reloc_free_move(breloc, move);
274 }
275 
276 static void
277 ftl_reloc_read_cb(struct ftl_io *io, void *arg, int status)
278 {
279 	struct ftl_reloc_move *move = arg;
280 	struct ftl_band_reloc *breloc = move->breloc;
281 
282 	breloc->num_outstanding--;
283 
284 	/* TODO: We should handle fail on relocation read. We need to inform */
285 	/* user that this group of blocks is bad (update l2p with bad block address and */
286 	/* put it to lba_map/sector_lba). Maybe we could also retry read with smaller granularity? */
287 	if (status) {
288 		SPDK_ERRLOG("Reloc read failed with status: %d\n", status);
289 		assert(false);
290 		return;
291 	}
292 
293 	move->state = FTL_RELOC_STATE_READ_LBA_MAP;
294 	move->io = NULL;
295 	spdk_ring_enqueue(breloc->move_queue, (void **)&move, 1, NULL);
296 }
297 
298 static void
299 ftl_reloc_iter_reset(struct ftl_band_reloc *breloc)
300 {
301 	memset(breloc->iter.zone_offset, 0, ftl_get_num_punits(breloc->band->dev) *
302 	       sizeof(*breloc->iter.zone_offset));
303 	breloc->iter.zone_current = 0;
304 }
305 
306 static size_t
307 ftl_reloc_iter_block_offset(struct ftl_band_reloc *breloc)
308 {
309 	size_t zone_offset = breloc->iter.zone_current * ftl_get_num_blocks_in_zone(breloc->parent->dev);
310 
311 	return breloc->iter.zone_offset[breloc->iter.zone_current] + zone_offset;
312 }
313 
314 static void
315 ftl_reloc_iter_next_zone(struct ftl_band_reloc *breloc)
316 {
317 	size_t num_zones = ftl_get_num_punits(breloc->band->dev);
318 
319 	breloc->iter.zone_current = (breloc->iter.zone_current + 1) % num_zones;
320 }
321 
322 static int
323 ftl_reloc_block_valid(struct ftl_band_reloc *breloc, size_t block_off)
324 {
325 	struct ftl_addr addr = ftl_band_addr_from_block_offset(breloc->band, block_off);
326 
327 	return ftl_addr_is_written(breloc->band, addr) &&
328 	       spdk_bit_array_get(breloc->reloc_map, block_off) &&
329 	       ftl_band_block_offset_valid(breloc->band, block_off);
330 }
331 
332 static int
333 ftl_reloc_iter_next(struct ftl_band_reloc *breloc, size_t *block_off)
334 {
335 	size_t zone = breloc->iter.zone_current;
336 
337 	*block_off = ftl_reloc_iter_block_offset(breloc);
338 
339 	if (ftl_reloc_iter_zone_done(breloc)) {
340 		return 0;
341 	}
342 
343 	breloc->iter.zone_offset[zone]++;
344 
345 	if (!ftl_reloc_block_valid(breloc, *block_off)) {
346 		ftl_reloc_clr_block(breloc, *block_off);
347 		return 0;
348 	}
349 
350 	return 1;
351 }
352 
353 static int
354 ftl_reloc_first_valid_block(struct ftl_band_reloc *breloc, size_t *block_off)
355 {
356 	size_t i, num_blocks = ftl_get_num_blocks_in_zone(breloc->parent->dev);
357 
358 	for (i = ftl_reloc_iter_zone_offset(breloc); i < num_blocks; ++i) {
359 		if (ftl_reloc_iter_next(breloc, block_off)) {
360 			return 1;
361 		}
362 	}
363 
364 	return 0;
365 }
366 
367 static int
368 ftl_reloc_iter_done(struct ftl_band_reloc *breloc)
369 {
370 	size_t i;
371 	size_t num_zones = ftl_get_num_punits(breloc->band->dev);
372 	size_t num_blocks = ftl_get_num_blocks_in_zone(breloc->parent->dev);
373 
374 	for (i = 0; i < num_zones; ++i) {
375 		if (breloc->iter.zone_offset[i] != num_blocks) {
376 			return 0;
377 		}
378 	}
379 
380 	return 1;
381 }
382 
383 static size_t
384 ftl_reloc_find_valid_blocks(struct ftl_band_reloc *breloc,
385 			    size_t _num_blocks, struct ftl_addr *addr)
386 {
387 	size_t block_off, num_blocks = 0;
388 
389 	if (!ftl_reloc_first_valid_block(breloc, &block_off)) {
390 		return 0;
391 	}
392 
393 	*addr = ftl_band_addr_from_block_offset(breloc->band, block_off);
394 
395 	for (num_blocks = 1; num_blocks < _num_blocks; num_blocks++) {
396 		if (!ftl_reloc_iter_next(breloc, &block_off)) {
397 			break;
398 		}
399 	}
400 
401 	return num_blocks;
402 }
403 
404 static size_t
405 ftl_reloc_next_blocks(struct ftl_band_reloc *breloc, struct ftl_addr *addr)
406 {
407 	size_t i, num_blocks = 0;
408 	struct spdk_ftl_dev *dev = breloc->parent->dev;
409 
410 	for (i = 0; i < ftl_get_num_punits(dev); ++i) {
411 		num_blocks = ftl_reloc_find_valid_blocks(breloc, breloc->parent->xfer_size, addr);
412 		ftl_reloc_iter_next_zone(breloc);
413 
414 		if (num_blocks || ftl_reloc_iter_done(breloc)) {
415 			break;
416 		}
417 	}
418 
419 	return num_blocks;
420 }
421 
422 static struct ftl_io *
423 ftl_reloc_io_init(struct ftl_band_reloc *breloc, struct ftl_reloc_move *move,
424 		  ftl_io_fn fn, enum ftl_io_type io_type, int flags)
425 {
426 	size_t block_off, i;
427 	struct ftl_addr addr = move->addr;
428 	struct ftl_io *io = NULL;
429 	struct ftl_io_init_opts opts = {
430 		.dev		= breloc->parent->dev,
431 		.band		= breloc->band,
432 		.size		= sizeof(*io),
433 		.flags		= flags | FTL_IO_INTERNAL | FTL_IO_PHYSICAL_MODE,
434 		.type		= io_type,
435 		.num_blocks	= move->num_blocks,
436 		.data		= move->data,
437 		.cb_fn		= fn,
438 	};
439 
440 	io = ftl_io_init_internal(&opts);
441 	if (!io) {
442 		return NULL;
443 	}
444 
445 	io->cb_ctx = move;
446 	io->addr = move->addr;
447 
448 	if (flags & FTL_IO_VECTOR_LBA) {
449 		for (i = 0; i < io->num_blocks; ++i, ++addr.offset) {
450 			block_off = ftl_band_block_offset_from_addr(breloc->band, addr);
451 
452 			if (!ftl_band_block_offset_valid(breloc->band, block_off)) {
453 				io->lba.vector[i] = FTL_LBA_INVALID;
454 				continue;
455 			}
456 
457 			io->lba.vector[i] = breloc->band->lba_map.map[block_off];
458 		}
459 	}
460 
461 	ftl_trace_lba_io_init(io->dev, io);
462 
463 	return io;
464 }
465 
466 static int
467 ftl_reloc_write(struct ftl_band_reloc *breloc, struct ftl_reloc_move *move)
468 {
469 	int io_flags =  FTL_IO_WEAK | FTL_IO_VECTOR_LBA | FTL_IO_BYPASS_CACHE;
470 
471 	if (spdk_likely(!move->io)) {
472 		move->io = ftl_reloc_io_init(breloc, move, ftl_reloc_write_cb,
473 					     FTL_IO_WRITE, io_flags);
474 		if (!move->io) {
475 			ftl_reloc_free_move(breloc, move);
476 			return -ENOMEM;
477 		}
478 	}
479 
480 	breloc->num_outstanding++;
481 	ftl_io_write(move->io);
482 	return 0;
483 }
484 
485 static int
486 ftl_reloc_read(struct ftl_band_reloc *breloc, struct ftl_reloc_move *move)
487 {
488 	struct ftl_addr addr = {};
489 
490 	move->num_blocks = ftl_reloc_next_blocks(breloc, &addr);
491 	move->breloc = breloc;
492 	move->addr = addr;
493 
494 	if (!move->num_blocks) {
495 		return 0;
496 	}
497 
498 	move->data = spdk_dma_malloc(FTL_BLOCK_SIZE * move->num_blocks, 4096, NULL);
499 	if (!move->data) {
500 		return -1;
501 	}
502 
503 	move->io = ftl_reloc_io_init(breloc, move, ftl_reloc_read_cb, FTL_IO_READ, 0);
504 	if (!move->io) {
505 		ftl_reloc_free_move(breloc, move);
506 		SPDK_ERRLOG("Failed to initialize io for relocation.");
507 		return -1;
508 	}
509 
510 	breloc->num_outstanding++;
511 	ftl_io_read(move->io);
512 	return 0;
513 }
514 
515 static void
516 ftl_reloc_process_moves(struct ftl_band_reloc *breloc)
517 {
518 	int rc = 0;
519 	size_t i, num_moves;
520 	struct ftl_reloc_move *moves[FTL_RELOC_MAX_MOVES] = {0};
521 	struct ftl_reloc *reloc = breloc->parent;
522 	struct ftl_reloc_move *move;
523 
524 	num_moves = spdk_ring_dequeue(breloc->move_queue, (void **)moves, reloc->max_qdepth);
525 
526 	for (i = 0; i < num_moves; ++i) {
527 		move = moves[i];
528 		assert(move != NULL);
529 		switch (move->state) {
530 		case FTL_RELOC_STATE_READ_LBA_MAP:
531 			rc = ftl_reloc_read_lba_map(breloc, move);
532 			break;
533 		case FTL_RELOC_STATE_READ:
534 			rc = ftl_reloc_read(breloc, move);
535 			break;
536 		case FTL_RELOC_STATE_WRITE:
537 			rc = ftl_reloc_write(breloc, move);
538 			break;
539 		default:
540 			assert(false);
541 			break;
542 		}
543 
544 		if (rc) {
545 			SPDK_ERRLOG("Move queue processing failed\n");
546 			assert(false);
547 		}
548 	}
549 }
550 
551 static bool
552 ftl_reloc_done(struct ftl_band_reloc *breloc)
553 {
554 	return !breloc->num_outstanding && !spdk_ring_count(breloc->move_queue);
555 }
556 
557 static void
558 ftl_reloc_release(struct ftl_band_reloc *breloc)
559 {
560 	struct ftl_reloc *reloc = breloc->parent;
561 	struct ftl_band *band = breloc->band;
562 
563 	ftl_reloc_iter_reset(breloc);
564 	ftl_band_release_lba_map(band);
565 	reloc->num_active--;
566 
567 	if (breloc->state == FTL_BAND_RELOC_STATE_HIGH_PRIO) {
568 		/* High prio band must be relocated as a whole and ANM events will be ignored */
569 		assert(breloc->num_blocks == 0 && ftl_band_empty(band));
570 		TAILQ_REMOVE(&reloc->prio_queue, breloc, entry);
571 		band->high_prio = 0;
572 		breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
573 	} else {
574 		assert(breloc->state == FTL_BAND_RELOC_STATE_ACTIVE);
575 		TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
576 		breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
577 
578 		/* If we got ANM event during relocation put such band back to pending queue */
579 		if (breloc->num_blocks != 0) {
580 			breloc->state = FTL_BAND_RELOC_STATE_PENDING;
581 			TAILQ_INSERT_TAIL(&reloc->pending_queue, breloc, entry);
582 			return;
583 		}
584 	}
585 
586 	if (ftl_band_empty(band) && band->state == FTL_BAND_STATE_CLOSED) {
587 		ftl_band_set_state(breloc->band, FTL_BAND_STATE_FREE);
588 
589 		if (breloc->defrag) {
590 			breloc->defrag = false;
591 			assert(reloc->num_defrag_bands > 0);
592 			reloc->num_defrag_bands--;
593 		}
594 	}
595 }
596 
597 static void
598 ftl_process_reloc(struct ftl_band_reloc *breloc)
599 {
600 	ftl_reloc_process_moves(breloc);
601 
602 	if (ftl_reloc_done(breloc)) {
603 		ftl_reloc_release(breloc);
604 	}
605 }
606 
607 static int
608 ftl_band_reloc_init(struct ftl_reloc *reloc, struct ftl_band_reloc *breloc,
609 		    struct ftl_band *band)
610 {
611 	breloc->band = band;
612 	breloc->parent = reloc;
613 
614 	breloc->reloc_map = spdk_bit_array_create(ftl_get_num_blocks_in_band(reloc->dev));
615 	if (!breloc->reloc_map) {
616 		SPDK_ERRLOG("Failed to initialize reloc map");
617 		return -1;
618 	}
619 
620 	breloc->iter.zone_offset = calloc(ftl_get_num_punits(band->dev),
621 					  sizeof(*breloc->iter.zone_offset));
622 	if (!breloc->iter.zone_offset) {
623 		SPDK_ERRLOG("Failed to initialize reloc iterator");
624 		return -1;
625 	}
626 
627 	breloc->move_queue = spdk_ring_create(SPDK_RING_TYPE_MP_SC,
628 					      reloc->max_qdepth * 2,
629 					      SPDK_ENV_SOCKET_ID_ANY);
630 	if (!breloc->move_queue) {
631 		SPDK_ERRLOG("Failed to initialize reloc write queue");
632 		return -1;
633 	}
634 
635 	breloc->moves = calloc(reloc->max_qdepth, sizeof(*breloc->moves));
636 	if (!breloc->moves) {
637 		return -1;
638 	}
639 
640 	return 0;
641 }
642 
643 static void
644 ftl_band_reloc_free(struct ftl_band_reloc *breloc)
645 {
646 	struct ftl_reloc *reloc;
647 	struct ftl_reloc_move *moves[FTL_RELOC_MAX_MOVES] = {};
648 	size_t i, num_moves;
649 
650 	if (!breloc) {
651 		return;
652 	}
653 
654 	assert(breloc->num_outstanding == 0);
655 	reloc = breloc->parent;
656 
657 	/* Drain write queue if there is active band relocation during shutdown */
658 	if (breloc->state == FTL_BAND_RELOC_STATE_ACTIVE ||
659 	    breloc->state == FTL_BAND_RELOC_STATE_HIGH_PRIO) {
660 		assert(reloc->halt);
661 		num_moves = spdk_ring_dequeue(breloc->move_queue, (void **)&moves, reloc->max_qdepth);
662 		for (i = 0; i < num_moves; ++i) {
663 			ftl_reloc_free_move(breloc, moves[i]);
664 		}
665 	}
666 
667 	spdk_ring_free(breloc->move_queue);
668 	spdk_bit_array_free(&breloc->reloc_map);
669 	free(breloc->iter.zone_offset);
670 	free(breloc->moves);
671 }
672 
673 struct ftl_reloc *
674 ftl_reloc_init(struct spdk_ftl_dev *dev)
675 {
676 	struct ftl_reloc *reloc;
677 	size_t i;
678 
679 	reloc = calloc(1, sizeof(*reloc));
680 	if (!reloc) {
681 		return NULL;
682 	}
683 
684 	reloc->dev = dev;
685 	reloc->halt = true;
686 	reloc->max_qdepth = dev->conf.max_reloc_qdepth;
687 	reloc->max_active = dev->conf.max_active_relocs;
688 	reloc->xfer_size = dev->xfer_size;
689 	reloc->num_defrag_bands = 0;
690 
691 	if (reloc->max_qdepth > FTL_RELOC_MAX_MOVES) {
692 		goto error;
693 	}
694 
695 	reloc->brelocs = calloc(ftl_get_num_bands(dev), sizeof(*reloc->brelocs));
696 	if (!reloc->brelocs) {
697 		goto error;
698 	}
699 
700 	for (i = 0; i < ftl_get_num_bands(reloc->dev); ++i) {
701 		if (ftl_band_reloc_init(reloc, &reloc->brelocs[i], &dev->bands[i])) {
702 			goto error;
703 		}
704 	}
705 
706 	TAILQ_INIT(&reloc->pending_queue);
707 	TAILQ_INIT(&reloc->active_queue);
708 	TAILQ_INIT(&reloc->prio_queue);
709 
710 	return reloc;
711 error:
712 	ftl_reloc_free(reloc);
713 	return NULL;
714 }
715 
716 void
717 ftl_reloc_free(struct ftl_reloc *reloc)
718 {
719 	size_t i;
720 
721 	if (!reloc) {
722 		return;
723 	}
724 
725 	for (i = 0; i < ftl_get_num_bands(reloc->dev); ++i) {
726 		ftl_band_reloc_free(&reloc->brelocs[i]);
727 	}
728 
729 	free(reloc->brelocs);
730 	free(reloc);
731 }
732 
733 bool
734 ftl_reloc_is_halted(const struct ftl_reloc *reloc)
735 {
736 	return reloc->halt;
737 }
738 
739 void
740 ftl_reloc_halt(struct ftl_reloc *reloc)
741 {
742 	reloc->halt = true;
743 }
744 
745 void
746 ftl_reloc_resume(struct ftl_reloc *reloc)
747 {
748 	reloc->halt = false;
749 }
750 
751 void
752 ftl_reloc(struct ftl_reloc *reloc)
753 {
754 	struct ftl_band_reloc *breloc, *tbreloc;
755 
756 	if (ftl_reloc_is_halted(reloc)) {
757 		return;
758 	}
759 
760 	/* Process first band from priority queue and return */
761 	breloc = TAILQ_FIRST(&reloc->prio_queue);
762 	if (breloc) {
763 		ftl_process_reloc(breloc);
764 		return;
765 	}
766 
767 	TAILQ_FOREACH_SAFE(breloc, &reloc->pending_queue, entry, tbreloc) {
768 		if (reloc->num_active == reloc->max_active) {
769 			break;
770 		}
771 
772 		/* TODO: Add handling relocation on open bands */
773 		if (breloc->band->state != FTL_BAND_STATE_CLOSED) {
774 			continue;
775 		}
776 
777 		ftl_reloc_prep(breloc);
778 		assert(breloc->state == FTL_BAND_RELOC_STATE_PENDING);
779 		TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
780 		breloc->state = FTL_BAND_RELOC_STATE_ACTIVE;
781 		TAILQ_INSERT_HEAD(&reloc->active_queue, breloc, entry);
782 	}
783 
784 	TAILQ_FOREACH_SAFE(breloc, &reloc->active_queue, entry, tbreloc) {
785 		assert(breloc->state == FTL_BAND_RELOC_STATE_ACTIVE);
786 		ftl_process_reloc(breloc);
787 	}
788 }
789 
790 void
791 ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset,
792 	      size_t num_blocks, int prio, bool is_defrag)
793 {
794 	struct ftl_band_reloc *breloc = &reloc->brelocs[band->id];
795 	size_t i;
796 
797 	/* No need to add anything if already at high prio - whole band should be relocated */
798 	if (!prio && band->high_prio) {
799 		return;
800 	}
801 
802 	pthread_spin_lock(&band->lba_map.lock);
803 	if (band->lba_map.num_vld == 0) {
804 		pthread_spin_unlock(&band->lba_map.lock);
805 
806 		/* If the band is closed and has no valid blocks, free it */
807 		if (band->state == FTL_BAND_STATE_CLOSED) {
808 			ftl_band_set_state(band, FTL_BAND_STATE_FREE);
809 		}
810 
811 		return;
812 	}
813 	pthread_spin_unlock(&band->lba_map.lock);
814 
815 	for (i = offset; i < offset + num_blocks; ++i) {
816 		if (spdk_bit_array_get(breloc->reloc_map, i)) {
817 			continue;
818 		}
819 		spdk_bit_array_set(breloc->reloc_map, i);
820 		breloc->num_blocks++;
821 	}
822 
823 	/* If the band is coming from the defrag process, mark it appropriately */
824 	if (is_defrag) {
825 		assert(offset == 0 && num_blocks == ftl_get_num_blocks_in_band(band->dev));
826 		reloc->num_defrag_bands++;
827 		breloc->defrag = true;
828 	}
829 
830 	if (!prio) {
831 		if (breloc->state == FTL_BAND_RELOC_STATE_INACTIVE) {
832 			breloc->state = FTL_BAND_RELOC_STATE_PENDING;
833 			TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry);
834 		}
835 	} else {
836 		bool active = false;
837 		/* If priority band is already on pending or active queue, remove it from it */
838 		switch (breloc->state) {
839 		case FTL_BAND_RELOC_STATE_PENDING:
840 			TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
841 			break;
842 		case FTL_BAND_RELOC_STATE_ACTIVE:
843 			active = true;
844 			TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
845 			break;
846 		default:
847 			break;
848 		}
849 
850 		breloc->state = FTL_BAND_RELOC_STATE_HIGH_PRIO;
851 		TAILQ_INSERT_TAIL(&reloc->prio_queue, breloc, entry);
852 
853 		/*
854 		 * If band has been already on active queue it doesn't need any additional
855 		 * resources
856 		 */
857 		if (!active) {
858 			ftl_reloc_prep(breloc);
859 		}
860 	}
861 }
862