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