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