xref: /spdk/lib/ftl/ftl_band.c (revision 94a84ae98590bea46939eb1dcd7a9876bd393b54)
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/crc32.h"
35 #include "spdk/likely.h"
36 #include "spdk/util.h"
37 #include "spdk/ftl.h"
38 
39 #include "ftl_band.h"
40 #include "ftl_io.h"
41 #include "ftl_core.h"
42 #include "ftl_reloc.h"
43 #include "ftl_debug.h"
44 
45 /* TODO: define some signature for meta version */
46 #define FTL_MD_VER 1
47 
48 struct __attribute__((packed)) ftl_md_hdr {
49 	/* Device instance */
50 	struct spdk_uuid	uuid;
51 
52 	/* Meta version */
53 	uint8_t			ver;
54 
55 	/* Sequence number */
56 	uint64_t		seq;
57 
58 	/* CRC32 checksum */
59 	uint32_t		checksum;
60 };
61 
62 /* End metadata layout stored on media (with all three being aligned to block size): */
63 /* - header */
64 /* - valid bitmap */
65 /* - LBA map */
66 struct __attribute__((packed)) ftl_tail_md {
67 	struct ftl_md_hdr	hdr;
68 
69 	/* Max number of blocks */
70 	uint64_t		num_blocks;
71 
72 	uint8_t			reserved[4059];
73 };
74 SPDK_STATIC_ASSERT(sizeof(struct ftl_tail_md) == FTL_BLOCK_SIZE, "Incorrect metadata size");
75 
76 struct __attribute__((packed)) ftl_head_md {
77 	struct ftl_md_hdr	hdr;
78 
79 	/* Number of defrag cycles */
80 	uint64_t		wr_cnt;
81 
82 	/* Number of surfaced LBAs */
83 	uint64_t		lba_cnt;
84 
85 	/* Transfer size */
86 	uint32_t		xfer_size;
87 };
88 
89 size_t
90 ftl_tail_md_hdr_num_blocks(void)
91 {
92 	return spdk_divide_round_up(sizeof(struct ftl_tail_md), FTL_BLOCK_SIZE);
93 }
94 
95 size_t
96 ftl_vld_map_num_blocks(const struct spdk_ftl_dev *dev)
97 {
98 	return spdk_divide_round_up(ftl_vld_map_size(dev), FTL_BLOCK_SIZE);
99 }
100 
101 size_t
102 ftl_lba_map_num_blocks(const struct spdk_ftl_dev *dev)
103 {
104 	return spdk_divide_round_up(ftl_get_num_blocks_in_band(dev) * sizeof(uint64_t), FTL_BLOCK_SIZE);
105 }
106 
107 size_t
108 ftl_head_md_num_blocks(const struct spdk_ftl_dev *dev)
109 {
110 	return dev->xfer_size;
111 }
112 
113 size_t
114 ftl_tail_md_num_blocks(const struct spdk_ftl_dev *dev)
115 {
116 	return spdk_divide_round_up(ftl_tail_md_hdr_num_blocks() +
117 				    ftl_vld_map_num_blocks(dev) +
118 				    ftl_lba_map_num_blocks(dev),
119 				    dev->xfer_size) * dev->xfer_size;
120 }
121 
122 static uint64_t
123 ftl_band_tail_md_offset(const struct ftl_band *band)
124 {
125 	return ftl_band_num_usable_blocks(band) -
126 	       ftl_tail_md_num_blocks(band->dev);
127 }
128 
129 int
130 ftl_band_full(struct ftl_band *band, size_t offset)
131 {
132 	return offset == ftl_band_tail_md_offset(band);
133 }
134 
135 void
136 ftl_band_write_failed(struct ftl_band *band)
137 {
138 	struct spdk_ftl_dev *dev = band->dev;
139 
140 	band->high_prio = 1;
141 
142 	ftl_reloc_add(dev->reloc, band, 0, ftl_get_num_blocks_in_band(dev), 1, true);
143 	ftl_band_set_state(band, FTL_BAND_STATE_CLOSED);
144 }
145 
146 static void
147 ftl_band_free_lba_map(struct ftl_band *band)
148 {
149 	struct spdk_ftl_dev *dev = band->dev;
150 	struct ftl_lba_map *lba_map = &band->lba_map;
151 
152 	assert(band->state == FTL_BAND_STATE_CLOSED ||
153 	       band->state == FTL_BAND_STATE_FREE);
154 	assert(lba_map->ref_cnt == 0);
155 	assert(lba_map->map != NULL);
156 	assert(!band->high_prio);
157 
158 	/* Verify that band's metadata is consistent with l2p */
159 	if (band->num_zones) {
160 		assert(ftl_band_validate_md(band) == true);
161 	}
162 
163 	spdk_mempool_put(dev->lba_pool, lba_map->dma_buf);
164 	lba_map->map = NULL;
165 	lba_map->dma_buf = NULL;
166 }
167 
168 static void
169 _ftl_band_set_free(struct ftl_band *band)
170 {
171 	struct spdk_ftl_dev *dev = band->dev;
172 	struct ftl_band *lband, *prev;
173 
174 	/* Remove the band from the closed band list */
175 	LIST_REMOVE(band, list_entry);
176 
177 	/* Keep the list sorted by band's write count */
178 	LIST_FOREACH(lband, &dev->free_bands, list_entry) {
179 		if (lband->wr_cnt > band->wr_cnt) {
180 			LIST_INSERT_BEFORE(lband, band, list_entry);
181 			break;
182 		}
183 		prev = lband;
184 	}
185 
186 	if (!lband) {
187 		if (LIST_EMPTY(&dev->free_bands)) {
188 			LIST_INSERT_HEAD(&dev->free_bands, band, list_entry);
189 		} else {
190 			LIST_INSERT_AFTER(prev, band, list_entry);
191 		}
192 	}
193 
194 #if defined(DEBUG)
195 	prev = NULL;
196 	LIST_FOREACH(lband, &dev->free_bands, list_entry) {
197 		if (!prev) {
198 			continue;
199 		}
200 		assert(prev->wr_cnt <= lband->wr_cnt);
201 	}
202 #endif
203 	dev->num_free++;
204 	ftl_apply_limits(dev);
205 }
206 
207 static void
208 _ftl_band_set_preparing(struct ftl_band *band)
209 {
210 	struct spdk_ftl_dev *dev = band->dev;
211 
212 	/* Remove band from free list */
213 	LIST_REMOVE(band, list_entry);
214 
215 	band->wr_cnt++;
216 
217 	assert(dev->num_free > 0);
218 	dev->num_free--;
219 
220 	ftl_apply_limits(dev);
221 }
222 
223 static void
224 _ftl_band_set_closed(struct ftl_band *band)
225 {
226 	struct spdk_ftl_dev *dev = band->dev;
227 
228 	/* Set the state as free_md() checks for that */
229 	band->state = FTL_BAND_STATE_CLOSED;
230 
231 	/* Free the lba map if there are no outstanding IOs */
232 	ftl_band_release_lba_map(band);
233 
234 	if (spdk_likely(band->num_zones)) {
235 		LIST_INSERT_HEAD(&dev->shut_bands, band, list_entry);
236 	} else {
237 		LIST_REMOVE(band, list_entry);
238 	}
239 }
240 
241 static uint32_t
242 ftl_md_calc_crc(const struct ftl_md_hdr *hdr, size_t size)
243 {
244 	size_t checkoff = offsetof(struct ftl_md_hdr, checksum);
245 	size_t mdoff = checkoff + sizeof(hdr->checksum);
246 	uint32_t crc;
247 
248 	crc = spdk_crc32c_update(hdr, checkoff, 0);
249 	return spdk_crc32c_update((const char *)hdr + mdoff, size - mdoff, crc);
250 }
251 
252 static void
253 ftl_set_md_hdr(struct ftl_band *band, struct ftl_md_hdr *hdr, size_t size)
254 {
255 	hdr->seq = band->seq;
256 	hdr->ver = FTL_MD_VER;
257 	hdr->uuid = band->dev->uuid;
258 	hdr->checksum = ftl_md_calc_crc(hdr, size);
259 }
260 
261 static int
262 ftl_pack_head_md(struct ftl_band *band)
263 {
264 	struct spdk_ftl_dev *dev = band->dev;
265 	struct ftl_head_md *head = band->lba_map.dma_buf;
266 
267 	head->wr_cnt = band->wr_cnt;
268 	head->lba_cnt = dev->num_lbas;
269 	head->xfer_size = dev->xfer_size;
270 	ftl_set_md_hdr(band, &head->hdr, sizeof(struct ftl_head_md));
271 
272 	return FTL_MD_SUCCESS;
273 }
274 
275 static int
276 ftl_pack_tail_md(struct ftl_band *band)
277 {
278 	struct spdk_ftl_dev *dev = band->dev;
279 	struct ftl_lba_map *lba_map = &band->lba_map;
280 	struct ftl_tail_md *tail = lba_map->dma_buf;
281 	void *vld_offset;
282 
283 	vld_offset = (char *)tail + ftl_tail_md_hdr_num_blocks() * FTL_BLOCK_SIZE;
284 
285 	/* Clear out the buffer */
286 	memset(tail, 0, ftl_tail_md_hdr_num_blocks() * FTL_BLOCK_SIZE);
287 	tail->num_blocks = ftl_get_num_blocks_in_band(dev);
288 
289 	pthread_spin_lock(&lba_map->lock);
290 	spdk_bit_array_store_mask(lba_map->vld, vld_offset);
291 	pthread_spin_unlock(&lba_map->lock);
292 
293 	ftl_set_md_hdr(band, &tail->hdr, ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE);
294 
295 	return FTL_MD_SUCCESS;
296 }
297 
298 static int
299 ftl_md_hdr_vld(struct spdk_ftl_dev *dev, const struct ftl_md_hdr *hdr, size_t size)
300 {
301 	if (spdk_uuid_compare(&dev->uuid, &hdr->uuid) != 0) {
302 		return FTL_MD_NO_MD;
303 	}
304 
305 	if (hdr->ver != FTL_MD_VER) {
306 		return FTL_MD_INVALID_VER;
307 	}
308 
309 	if (ftl_md_calc_crc(hdr, size) != hdr->checksum) {
310 		return FTL_MD_INVALID_CRC;
311 	}
312 
313 	return FTL_MD_SUCCESS;
314 }
315 
316 static int
317 ftl_unpack_tail_md(struct ftl_band *band)
318 {
319 	struct spdk_ftl_dev *dev = band->dev;
320 	void *vld_offset;
321 	struct ftl_lba_map *lba_map = &band->lba_map;
322 	struct ftl_tail_md *tail = lba_map->dma_buf;
323 	int rc;
324 
325 	vld_offset = (char *)tail + ftl_tail_md_hdr_num_blocks() * FTL_BLOCK_SIZE;
326 
327 	rc = ftl_md_hdr_vld(dev, &tail->hdr, ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE);
328 	if (rc) {
329 		return rc;
330 	}
331 
332 	/*
333 	 * When restoring from a dirty shutdown it's possible old tail meta wasn't yet cleared -
334 	 * band had saved head meta, but didn't manage to send erase to all zones.
335 	 * The already found tail md header is valid, but inconsistent with the head meta. Treat
336 	 * such a band as open/without valid tail md.
337 	 */
338 	if (band->seq != tail->hdr.seq) {
339 		return FTL_MD_NO_MD;
340 	}
341 
342 	if (tail->num_blocks != ftl_get_num_blocks_in_band(dev)) {
343 		return FTL_MD_INVALID_SIZE;
344 	}
345 
346 	spdk_bit_array_load_mask(lba_map->vld, vld_offset);
347 
348 	return FTL_MD_SUCCESS;
349 }
350 
351 static int
352 ftl_unpack_head_md(struct ftl_band *band)
353 {
354 	struct spdk_ftl_dev *dev = band->dev;
355 	struct ftl_head_md *head = band->lba_map.dma_buf;
356 	int rc;
357 
358 	rc = ftl_md_hdr_vld(dev, &head->hdr, sizeof(struct ftl_head_md));
359 	if (rc) {
360 		return rc;
361 	}
362 
363 	band->seq = head->hdr.seq;
364 	band->wr_cnt = head->wr_cnt;
365 
366 	if (dev->global_md.num_lbas == 0) {
367 		dev->global_md.num_lbas = head->lba_cnt;
368 	}
369 
370 	if (dev->global_md.num_lbas != head->lba_cnt) {
371 		return FTL_MD_INVALID_SIZE;
372 	}
373 
374 	if (dev->xfer_size != head->xfer_size) {
375 		return FTL_MD_INVALID_SIZE;
376 	}
377 
378 	return FTL_MD_SUCCESS;
379 }
380 
381 struct ftl_addr
382 ftl_band_tail_md_addr(struct ftl_band *band)
383 {
384 	struct ftl_addr addr = {};
385 	struct ftl_zone *zone;
386 	struct spdk_ftl_dev *dev = band->dev;
387 	size_t xfer_size = dev->xfer_size;
388 	size_t num_req = ftl_band_tail_md_offset(band) / xfer_size;
389 	size_t i;
390 
391 	if (spdk_unlikely(!band->num_zones)) {
392 		return ftl_to_addr(FTL_ADDR_INVALID);
393 	}
394 
395 	/* Metadata should be aligned to xfer size */
396 	assert(ftl_band_tail_md_offset(band) % xfer_size == 0);
397 
398 	zone = CIRCLEQ_FIRST(&band->zones);
399 	for (i = 0; i < num_req % band->num_zones; ++i) {
400 		zone = ftl_band_next_zone(band, zone);
401 	}
402 
403 	addr.offset = (num_req / band->num_zones) * xfer_size;
404 	addr.offset += zone->info.zone_id;
405 
406 	return addr;
407 }
408 
409 struct ftl_addr
410 ftl_band_head_md_addr(struct ftl_band *band)
411 {
412 	if (spdk_unlikely(!band->num_zones)) {
413 		return ftl_to_addr(FTL_ADDR_INVALID);
414 	}
415 
416 	return ftl_to_addr(CIRCLEQ_FIRST(&band->zones)->info.zone_id);
417 }
418 
419 void
420 ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state)
421 {
422 	switch (state) {
423 	case FTL_BAND_STATE_FREE:
424 		assert(band->state == FTL_BAND_STATE_CLOSED);
425 		_ftl_band_set_free(band);
426 		break;
427 
428 	case FTL_BAND_STATE_PREP:
429 		assert(band->state == FTL_BAND_STATE_FREE);
430 		_ftl_band_set_preparing(band);
431 		break;
432 
433 	case FTL_BAND_STATE_CLOSED:
434 		if (band->state != FTL_BAND_STATE_CLOSED) {
435 			assert(band->state == FTL_BAND_STATE_CLOSING || band->high_prio);
436 			_ftl_band_set_closed(band);
437 		}
438 		break;
439 
440 	default:
441 		break;
442 	}
443 
444 	band->state = state;
445 }
446 
447 void
448 ftl_band_set_addr(struct ftl_band *band, uint64_t lba, struct ftl_addr addr)
449 {
450 	struct ftl_lba_map *lba_map = &band->lba_map;
451 	uint64_t offset;
452 
453 	assert(lba != FTL_LBA_INVALID);
454 
455 	offset = ftl_band_block_offset_from_addr(band, addr);
456 	pthread_spin_lock(&lba_map->lock);
457 
458 	lba_map->num_vld++;
459 	lba_map->map[offset] = lba;
460 	spdk_bit_array_set(lba_map->vld, offset);
461 
462 	pthread_spin_unlock(&lba_map->lock);
463 }
464 
465 size_t
466 ftl_band_age(const struct ftl_band *band)
467 {
468 	return (size_t)(band->dev->seq - band->seq);
469 }
470 
471 size_t
472 ftl_band_num_usable_blocks(const struct ftl_band *band)
473 {
474 	return band->num_zones * ftl_get_num_blocks_in_zone(band->dev);
475 }
476 
477 size_t
478 ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset)
479 {
480 	size_t tail_md_offset = ftl_band_tail_md_offset(band);
481 
482 	if (spdk_unlikely(offset <= ftl_head_md_num_blocks(band->dev))) {
483 		return ftl_band_user_blocks(band);
484 	}
485 
486 	if (spdk_unlikely(offset > tail_md_offset)) {
487 		return 0;
488 	}
489 
490 	return tail_md_offset - offset;
491 }
492 
493 size_t
494 ftl_band_user_blocks(const struct ftl_band *band)
495 {
496 	return ftl_band_num_usable_blocks(band) -
497 	       ftl_head_md_num_blocks(band->dev) -
498 	       ftl_tail_md_num_blocks(band->dev);
499 }
500 
501 struct ftl_band *
502 ftl_band_from_addr(struct spdk_ftl_dev *dev, struct ftl_addr addr)
503 {
504 	size_t band_id = ftl_addr_get_band(dev, addr);
505 
506 	assert(band_id < ftl_get_num_bands(dev));
507 	return &dev->bands[band_id];
508 }
509 
510 struct ftl_zone *
511 ftl_band_zone_from_addr(struct ftl_band *band, struct ftl_addr addr)
512 {
513 	size_t pu_id = ftl_addr_get_punit(band->dev, addr);
514 
515 	assert(pu_id < ftl_get_num_punits(band->dev));
516 	return &band->zone_buf[pu_id];
517 }
518 
519 uint64_t
520 ftl_band_block_offset_from_addr(struct ftl_band *band, struct ftl_addr addr)
521 {
522 	assert(ftl_addr_get_band(band->dev, addr) == band->id);
523 	assert(ftl_addr_get_punit(band->dev, addr) < ftl_get_num_punits(band->dev));
524 	return addr.offset % ftl_get_num_blocks_in_band(band->dev);
525 }
526 
527 struct ftl_addr
528 ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr, size_t num_blocks)
529 {
530 	struct spdk_ftl_dev *dev = band->dev;
531 	struct ftl_zone *zone;
532 	size_t num_xfers, num_stripes;
533 	uint64_t offset;
534 
535 	assert(ftl_addr_get_band(dev, addr) == band->id);
536 
537 	offset = ftl_addr_get_zone_offset(dev, addr);
538 	zone = ftl_band_zone_from_addr(band, addr);
539 
540 	num_blocks += (offset % dev->xfer_size);
541 	offset  -= (offset % dev->xfer_size);
542 
543 #if defined(DEBUG)
544 	/* Check that the number of zones has not been changed */
545 	struct ftl_zone *_zone;
546 	size_t _num_zones = 0;
547 	CIRCLEQ_FOREACH(_zone, &band->zones, circleq) {
548 		if (spdk_likely(_zone->info.state != SPDK_BDEV_ZONE_STATE_OFFLINE)) {
549 			_num_zones++;
550 		}
551 	}
552 	assert(band->num_zones == _num_zones);
553 #endif
554 	assert(band->num_zones != 0);
555 	num_stripes = (num_blocks / dev->xfer_size) / band->num_zones;
556 	offset += num_stripes * dev->xfer_size;
557 	num_blocks -= num_stripes * dev->xfer_size * band->num_zones;
558 
559 	if (offset > ftl_get_num_blocks_in_zone(dev)) {
560 		return ftl_to_addr(FTL_ADDR_INVALID);
561 	}
562 
563 	num_xfers = num_blocks / dev->xfer_size;
564 	for (size_t i = 0; i < num_xfers; ++i) {
565 		/* When the last zone is reached the block part of the address */
566 		/* needs to be increased by xfer_size */
567 		if (ftl_band_zone_is_last(band, zone)) {
568 			offset += dev->xfer_size;
569 			if (offset > ftl_get_num_blocks_in_zone(dev)) {
570 				return ftl_to_addr(FTL_ADDR_INVALID);
571 			}
572 		}
573 
574 		zone = ftl_band_next_operational_zone(band, zone);
575 		assert(zone);
576 
577 		num_blocks -= dev->xfer_size;
578 	}
579 
580 	if (num_blocks) {
581 		offset += num_blocks;
582 		if (offset > ftl_get_num_blocks_in_zone(dev)) {
583 			return ftl_to_addr(FTL_ADDR_INVALID);
584 		}
585 	}
586 
587 	addr.offset = zone->info.zone_id + offset;
588 	return addr;
589 }
590 
591 static size_t
592 ftl_xfer_offset_from_addr(struct ftl_band *band, struct ftl_addr addr)
593 {
594 	struct ftl_zone *zone, *current_zone;
595 	unsigned int punit_offset = 0;
596 	size_t num_stripes, xfer_size = band->dev->xfer_size;
597 	uint64_t offset;
598 
599 	assert(ftl_addr_get_band(band->dev, addr) == band->id);
600 
601 	offset = ftl_addr_get_zone_offset(band->dev, addr);
602 	num_stripes = (offset / xfer_size) * band->num_zones;
603 
604 	current_zone = ftl_band_zone_from_addr(band, addr);
605 	CIRCLEQ_FOREACH(zone, &band->zones, circleq) {
606 		if (current_zone == zone) {
607 			break;
608 		}
609 		punit_offset++;
610 	}
611 
612 	return xfer_size * (num_stripes + punit_offset) + offset % xfer_size;
613 }
614 
615 struct ftl_addr
616 ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
617 {
618 	struct ftl_addr addr = { .offset = 0 };
619 
620 	addr.offset = block_off + band->id * ftl_get_num_blocks_in_band(band->dev);
621 	return addr;
622 }
623 
624 struct ftl_addr
625 ftl_band_next_addr(struct ftl_band *band, struct ftl_addr addr, size_t offset)
626 {
627 	uint64_t block_off = ftl_band_block_offset_from_addr(band, addr);
628 	return ftl_band_addr_from_block_offset(band, block_off + offset);
629 }
630 
631 void
632 ftl_band_acquire_lba_map(struct ftl_band *band)
633 {
634 	assert(band->lba_map.map != NULL);
635 	band->lba_map.ref_cnt++;
636 }
637 
638 int
639 ftl_band_alloc_lba_map(struct ftl_band *band)
640 {
641 	struct spdk_ftl_dev *dev = band->dev;
642 	struct ftl_lba_map *lba_map = &band->lba_map;
643 
644 	assert(lba_map->ref_cnt == 0);
645 	assert(lba_map->map == NULL);
646 
647 	lba_map->dma_buf = spdk_mempool_get(dev->lba_pool);
648 
649 	if (!lba_map->dma_buf) {
650 		return -1;
651 	}
652 
653 	memset(lba_map->dma_buf, 0, ftl_lba_map_pool_elem_size(band->dev));
654 
655 	lba_map->map = (uint64_t *)((char *)lba_map->dma_buf + FTL_BLOCK_SIZE *
656 				    (ftl_tail_md_hdr_num_blocks() + ftl_vld_map_num_blocks(dev)));
657 
658 	lba_map->segments = (char *)lba_map->dma_buf + ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE;
659 
660 	ftl_band_acquire_lba_map(band);
661 	return 0;
662 }
663 
664 void
665 ftl_band_release_lba_map(struct ftl_band *band)
666 {
667 	struct ftl_lba_map *lba_map = &band->lba_map;
668 
669 	assert(lba_map->map != NULL);
670 	assert(lba_map->ref_cnt > 0);
671 	lba_map->ref_cnt--;
672 
673 	if (lba_map->ref_cnt == 0) {
674 		ftl_band_free_lba_map(band);
675 	}
676 }
677 
678 static void
679 ftl_read_md_cb(struct ftl_io *io, void *arg, int status)
680 {
681 	struct ftl_md_io *md_io = (struct ftl_md_io *)io;
682 
683 	if (!status) {
684 		status = md_io->pack_fn(md_io->io.band);
685 	} else {
686 		status = FTL_MD_IO_FAILURE;
687 	}
688 
689 	md_io->cb_fn(io, md_io->cb_ctx, status);
690 }
691 
692 static struct ftl_md_io *
693 ftl_io_init_md_read(struct spdk_ftl_dev *dev, struct ftl_addr addr,
694 		    struct ftl_band *band, size_t num_blocks, void *buf,
695 		    ftl_io_fn fn, ftl_md_pack_fn pack_fn, ftl_io_fn cb_fn, void *cb_ctx)
696 {
697 	struct ftl_md_io *io;
698 	struct ftl_io_init_opts opts = {
699 		.dev		= dev,
700 		.io		= NULL,
701 		.band		= band,
702 		.size		= sizeof(*io),
703 		.flags		= FTL_IO_MD | FTL_IO_PHYSICAL_MODE,
704 		.type		= FTL_IO_READ,
705 		.num_blocks	= num_blocks,
706 		.cb_fn		= fn,
707 		.iovs		= {
708 			{
709 				.iov_base = buf,
710 				.iov_len = num_blocks * FTL_BLOCK_SIZE,
711 			}
712 		},
713 		.iovcnt		= 1,
714 	};
715 
716 	io = (struct ftl_md_io *)ftl_io_init_internal(&opts);
717 	if (!io) {
718 		return NULL;
719 	}
720 
721 	io->io.addr = addr;
722 	io->pack_fn = pack_fn;
723 	io->cb_fn = cb_fn;
724 	io->cb_ctx = cb_ctx;
725 
726 	return io;
727 }
728 
729 static struct ftl_io *
730 ftl_io_init_md_write(struct spdk_ftl_dev *dev, struct ftl_band *band,
731 		     void *data, size_t num_blocks, ftl_io_fn cb)
732 {
733 	struct ftl_io_init_opts opts = {
734 		.dev		= dev,
735 		.io		= NULL,
736 		.band		= band,
737 		.size		= sizeof(struct ftl_io),
738 		.flags		= FTL_IO_MD | FTL_IO_PHYSICAL_MODE,
739 		.type		= FTL_IO_WRITE,
740 		.num_blocks	= num_blocks,
741 		.cb_fn		= cb,
742 		.iovs		= {
743 			{
744 				.iov_base = data,
745 				.iov_len = num_blocks * FTL_BLOCK_SIZE,
746 			}
747 		},
748 		.iovcnt		= 1,
749 		.md		= NULL,
750 	};
751 
752 	return ftl_io_init_internal(&opts);
753 }
754 
755 static int
756 ftl_band_write_md(struct ftl_band *band, size_t num_blocks,
757 		  ftl_md_pack_fn md_fn, ftl_io_fn cb)
758 {
759 	struct spdk_ftl_dev *dev = band->dev;
760 	struct ftl_io *io;
761 
762 	io = ftl_io_init_md_write(dev, band, band->lba_map.dma_buf, num_blocks, cb);
763 	if (!io) {
764 		return -ENOMEM;
765 	}
766 
767 	md_fn(band);
768 
769 	ftl_io_write(io);
770 	return 0;
771 }
772 
773 void
774 ftl_band_md_clear(struct ftl_band *band)
775 {
776 	band->seq = 0;
777 	band->wr_cnt = 0;
778 	band->lba_map.num_vld = 0;
779 	band->lba_map.map = NULL;
780 }
781 
782 int
783 ftl_band_write_head_md(struct ftl_band *band, ftl_io_fn cb)
784 {
785 	return ftl_band_write_md(band, ftl_head_md_num_blocks(band->dev),
786 				 ftl_pack_head_md, cb);
787 }
788 
789 int
790 ftl_band_write_tail_md(struct ftl_band *band, ftl_io_fn cb)
791 {
792 	return ftl_band_write_md(band, ftl_tail_md_num_blocks(band->dev),
793 				 ftl_pack_tail_md, cb);
794 }
795 
796 static struct ftl_addr
797 ftl_band_lba_map_addr(struct ftl_band *band, size_t offset)
798 {
799 	return ftl_band_next_xfer_addr(band, band->tail_md_addr,
800 				       ftl_tail_md_hdr_num_blocks() +
801 				       ftl_vld_map_num_blocks(band->dev) +
802 				       offset);
803 }
804 
805 static int
806 ftl_band_read_md(struct ftl_band *band, size_t num_blocks, struct ftl_addr start_addr,
807 		 void *buf, ftl_io_fn fn, ftl_md_pack_fn pack_fn, ftl_io_fn cb_fn, void *cb_ctx)
808 {
809 	struct spdk_ftl_dev *dev = band->dev;
810 	struct ftl_md_io *io;
811 
812 	if (spdk_unlikely(!band->num_zones)) {
813 		return -ENOENT;
814 	}
815 
816 	io = ftl_io_init_md_read(dev, start_addr, band, num_blocks, buf, fn, pack_fn, cb_fn, cb_ctx);
817 	if (!io) {
818 		return -ENOMEM;
819 	}
820 
821 	ftl_io_read((struct ftl_io *)io);
822 	return 0;
823 }
824 
825 int
826 ftl_band_read_tail_md(struct ftl_band *band, struct ftl_addr addr, ftl_io_fn cb_fn, void *cb_ctx)
827 {
828 	return ftl_band_read_md(band, ftl_tail_md_num_blocks(band->dev), addr, band->lba_map.dma_buf,
829 				ftl_read_md_cb, ftl_unpack_tail_md, cb_fn, cb_ctx);
830 }
831 
832 static size_t
833 ftl_lba_map_request_segment_done(struct ftl_lba_map_request *request, size_t offset,
834 				 size_t num_segments)
835 {
836 	size_t i, num_done = 0;
837 
838 	for (i = offset; i < offset + num_segments; ++i) {
839 		if (spdk_bit_array_get(request->segments, i)) {
840 			spdk_bit_array_clear(request->segments, offset);
841 			num_done++;
842 		}
843 	}
844 
845 	assert(request->num_pending >= num_done);
846 	request->num_pending -= num_done;
847 
848 	return num_done;
849 }
850 
851 static void
852 ftl_lba_map_set_segment_state(struct ftl_lba_map *lba_map, size_t offset, size_t num_segments,
853 			      enum ftl_lba_map_seg_state state)
854 {
855 	size_t i;
856 
857 	for (i = offset; i < offset + num_segments; ++i) {
858 		lba_map->segments[i] = state;
859 	}
860 }
861 
862 static void
863 ftl_lba_map_request_free(struct spdk_ftl_dev *dev, struct ftl_lba_map_request *request)
864 {
865 	spdk_bit_array_clear_mask(request->segments);
866 	spdk_mempool_put(dev->lba_request_pool, request);
867 }
868 
869 static void
870 ftl_process_lba_map_requests(struct spdk_ftl_dev *dev, struct ftl_lba_map *lba_map, size_t offset,
871 			     size_t num_segments, int status)
872 {
873 	struct ftl_lba_map_request *request, *trequest;
874 	size_t num_done;
875 
876 	LIST_FOREACH_SAFE(request, &lba_map->request_list, list_entry, trequest) {
877 		num_done = ftl_lba_map_request_segment_done(request, offset, num_segments);
878 		if (request->num_pending == 0 || (status && num_done)) {
879 			request->cb(NULL, request->cb_ctx, status);
880 			LIST_REMOVE(request, list_entry);
881 			ftl_lba_map_request_free(dev, request);
882 		}
883 	}
884 }
885 
886 static size_t
887 ftl_lba_map_offset_from_addr(struct ftl_band *band, struct ftl_addr addr)
888 {
889 	size_t offset;
890 	struct ftl_addr start_addr = ftl_band_lba_map_addr(band, 0);
891 
892 	offset =  ftl_xfer_offset_from_addr(band, addr) - ftl_xfer_offset_from_addr(band, start_addr);
893 	assert(offset < ftl_lba_map_num_blocks(band->dev));
894 
895 	return offset;
896 }
897 
898 static void
899 ftl_read_lba_map_cb(struct ftl_io *io, void *arg, int status)
900 {
901 	struct ftl_lba_map *lba_map = &io->band->lba_map;
902 	uint64_t block_off;
903 
904 	block_off = ftl_lba_map_offset_from_addr(io->band, io->addr);
905 	assert(block_off + io->num_blocks <= ftl_lba_map_num_blocks(io->dev));
906 
907 	if (!status) {
908 		ftl_lba_map_set_segment_state(lba_map, block_off, io->num_blocks,
909 					      FTL_LBA_MAP_SEG_CACHED);
910 	}
911 
912 	ftl_process_lba_map_requests(io->dev, lba_map, block_off, io->num_blocks, status);
913 }
914 
915 static struct ftl_lba_map_request *
916 ftl_lba_map_alloc_request(struct ftl_band *band, size_t offset, size_t num_segments,
917 			  ftl_io_fn cb, void *cb_ctx)
918 {
919 	struct ftl_lba_map_request *request;
920 	struct spdk_ftl_dev *dev = band->dev;
921 	size_t i;
922 
923 	request = spdk_mempool_get(dev->lba_request_pool);
924 	if (!request) {
925 		return NULL;
926 	}
927 
928 	request->cb = cb;
929 	request->cb_ctx = cb_ctx;
930 	request->num_pending = num_segments;
931 
932 	for (i = offset; i < offset + num_segments; ++i) {
933 		spdk_bit_array_set(request->segments, i);
934 	}
935 
936 	return request;
937 }
938 
939 static size_t
940 ftl_lba_map_num_clear_segments(struct ftl_lba_map *lba_map,
941 			       size_t offset, size_t num_segments)
942 {
943 	size_t i, cnt = 0;
944 
945 	for (i = offset; i < offset + num_segments; ++i) {
946 		if (lba_map->segments[i] != FTL_LBA_MAP_SEG_CLEAR) {
947 			break;
948 		}
949 		cnt++;
950 	}
951 
952 	return cnt;
953 }
954 
955 int
956 ftl_band_read_lba_map(struct ftl_band *band, size_t offset, size_t lba_cnt,
957 		      ftl_io_fn cb_fn, void *cb_ctx)
958 {
959 	size_t num_blocks, block_off, num_read, num_segments;
960 	struct ftl_lba_map *lba_map = &band->lba_map;
961 	struct ftl_lba_map_request *request;
962 	int rc = 0;
963 
964 	block_off = offset / FTL_NUM_LBA_IN_BLOCK;
965 	num_segments = spdk_divide_round_up(offset + lba_cnt, FTL_NUM_LBA_IN_BLOCK);
966 	num_blocks = num_segments - block_off;
967 	assert(block_off + num_blocks <= ftl_lba_map_num_blocks(band->dev));
968 
969 	request = ftl_lba_map_alloc_request(band, block_off, num_blocks, cb_fn, cb_ctx);
970 	if (!request) {
971 		return -ENOMEM;
972 	}
973 
974 	while (num_blocks) {
975 		if (lba_map->segments[block_off] != FTL_LBA_MAP_SEG_CLEAR) {
976 			if (lba_map->segments[block_off] == FTL_LBA_MAP_SEG_CACHED) {
977 				ftl_lba_map_request_segment_done(request, block_off, 1);
978 			}
979 			num_blocks--;
980 			block_off++;
981 			continue;
982 		}
983 
984 		num_read = ftl_lba_map_num_clear_segments(lba_map, block_off, num_blocks);
985 		ftl_lba_map_set_segment_state(lba_map, block_off, num_read,
986 					      FTL_LBA_MAP_SEG_PENDING);
987 
988 		rc = ftl_band_read_md(band, num_read, ftl_band_lba_map_addr(band, block_off),
989 				      (char *)band->lba_map.map + block_off * FTL_BLOCK_SIZE,
990 				      ftl_read_lba_map_cb, NULL, cb_fn, cb_ctx);
991 		if (rc) {
992 			ftl_lba_map_request_free(band->dev, request);
993 			return rc;
994 		}
995 
996 		assert(num_blocks >= num_read);
997 		num_blocks -= num_read;
998 		block_off += num_read;
999 	}
1000 
1001 	if (request->num_pending) {
1002 		LIST_INSERT_HEAD(&lba_map->request_list, request, list_entry);
1003 	} else {
1004 		cb_fn(NULL, cb_ctx, 0);
1005 		ftl_lba_map_request_free(band->dev, request);
1006 	}
1007 
1008 	return rc;
1009 }
1010 
1011 int
1012 ftl_band_read_head_md(struct ftl_band *band, ftl_io_fn cb_fn, void *cb_ctx)
1013 {
1014 	return ftl_band_read_md(band,
1015 				ftl_head_md_num_blocks(band->dev),
1016 				ftl_band_head_md_addr(band),
1017 				band->lba_map.dma_buf,
1018 				ftl_read_md_cb,
1019 				ftl_unpack_head_md,
1020 				cb_fn,
1021 				cb_ctx);
1022 }
1023 
1024 void
1025 ftl_band_remove_zone(struct ftl_band *band, struct ftl_zone *zone)
1026 {
1027 	CIRCLEQ_REMOVE(&band->zones, zone, circleq);
1028 	band->num_zones--;
1029 }
1030 
1031 int
1032 ftl_band_write_prep(struct ftl_band *band)
1033 {
1034 	struct spdk_ftl_dev *dev = band->dev;
1035 
1036 	if (ftl_band_alloc_lba_map(band)) {
1037 		return -1;
1038 	}
1039 
1040 	band->seq = ++dev->seq;
1041 	return 0;
1042 }
1043 
1044 struct ftl_zone *
1045 ftl_band_next_operational_zone(struct ftl_band *band, struct ftl_zone *zone)
1046 {
1047 	struct ftl_zone *result = NULL;
1048 	struct ftl_zone *entry;
1049 
1050 	if (spdk_unlikely(!band->num_zones)) {
1051 		return NULL;
1052 	}
1053 
1054 	/* Erasing band may fail after it was assigned to wptr. */
1055 	/* In such a case zone is no longer in band->zones queue. */
1056 	if (spdk_likely(zone->info.state != SPDK_BDEV_ZONE_STATE_OFFLINE)) {
1057 		result = ftl_band_next_zone(band, zone);
1058 	} else {
1059 		CIRCLEQ_FOREACH_REVERSE(entry, &band->zones, circleq) {
1060 			if (entry->info.zone_id > zone->info.zone_id) {
1061 				result = entry;
1062 			} else {
1063 				if (!result) {
1064 					result = CIRCLEQ_FIRST(&band->zones);
1065 				}
1066 				break;
1067 			}
1068 		}
1069 	}
1070 
1071 	return result;
1072 }
1073 
1074 void
1075 ftl_band_clear_lba_map(struct ftl_band *band)
1076 {
1077 	struct ftl_lba_map *lba_map = &band->lba_map;
1078 	size_t num_segments;
1079 
1080 	spdk_bit_array_clear_mask(lba_map->vld);
1081 	memset(lba_map->map, 0, ftl_lba_map_num_blocks(band->dev) * FTL_BLOCK_SIZE);
1082 
1083 	/* For open band all lba map segments are already cached */
1084 	assert(band->state == FTL_BAND_STATE_PREP);
1085 	num_segments = spdk_divide_round_up(ftl_get_num_blocks_in_band(band->dev), FTL_NUM_LBA_IN_BLOCK);
1086 	ftl_lba_map_set_segment_state(&band->lba_map, 0, num_segments, FTL_LBA_MAP_SEG_CACHED);
1087 
1088 	lba_map->num_vld = 0;
1089 }
1090 
1091 size_t
1092 ftl_lba_map_pool_elem_size(struct spdk_ftl_dev *dev)
1093 {
1094 	/* Map pool element holds the whole tail md + segments map */
1095 	return ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE +
1096 	       spdk_divide_round_up(ftl_get_num_blocks_in_band(dev), FTL_NUM_LBA_IN_BLOCK);
1097 }
1098