From d6234332fbb6e0e1ddb3fbff92c72665f2e168ea Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Fri, 20 Sep 2019 07:26:16 -0400 Subject: [PATCH] lib/ftl: Represent ftl_addr just with the offset value This patch removes parallel unit and zone id fields from ftl_addr struct. Change-Id: Ica42208eafdbbecab60430708197f5f3ba6167d6 Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468701 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto Reviewed-by: Konrad Sztyber Community-CI: SPDK CI Jenkins --- lib/ftl/ftl_addr.h | 15 ++-- lib/ftl/ftl_band.c | 76 +++++++++----------- lib/ftl/ftl_core.c | 41 ++++++----- lib/ftl/ftl_core.h | 58 ++++++++------- lib/ftl/ftl_debug.c | 2 +- lib/ftl/ftl_debug.h | 3 +- lib/ftl/ftl_init.c | 9 ++- lib/ftl/ftl_io.c | 2 +- lib/ftl/ftl_restore.c | 4 +- lib/ftl/ftl_trace.c | 4 +- test/unit/lib/ftl/common/utils.c | 11 ++- test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c | 75 +++++++++---------- test/unit/lib/ftl/ftl_md/ftl_md_ut.c | 2 +- test/unit/lib/ftl/ftl_ppa/ftl_ppa_ut.c | 50 ++----------- test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c | 13 +--- test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c | 4 +- 16 files changed, 149 insertions(+), 220 deletions(-) diff --git a/lib/ftl/ftl_addr.h b/lib/ftl/ftl_addr.h index 9f74fe4e2..36d2ffb00 100644 --- a/lib/ftl/ftl_addr.h +++ b/lib/ftl/ftl_addr.h @@ -45,20 +45,13 @@ /* This structure represents on-disk address. It can have one of the following */ /* formats: */ -/* - addr describing the raw address */ +/* - offset inside the disk */ /* - cache_offset inside the cache (indicated by the cached flag) */ /* - packed version of the two formats above (can be only used when the */ -/* raw address can be represented in less than 32 bits) */ +/* offset can be represented in less than 32 bits) */ /* Packed format is used, when possible, to avoid wasting RAM on the L2P table. */ struct ftl_addr { union { - struct { - uint64_t offset : 32; - uint64_t zone_id : 16; - uint64_t pu : 15; - uint64_t rsvd : 1; - }; - struct { uint64_t cache_offset : 63; uint64_t cached : 1; @@ -71,12 +64,12 @@ struct ftl_addr { uint32_t cached : 1; }; - uint32_t addr; + uint32_t offset; }; uint32_t rsvd; } pack; - uint64_t addr; + uint64_t offset; }; }; diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 757b80a4a..81426c197 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -405,8 +405,7 @@ ftl_band_tail_md_addr(struct ftl_band *band) } addr.offset = (num_req / band->num_zones) * xfer_size; - addr.zone_id = band->id; - addr.pu = zone->start_addr.pu; + addr.offset += zone->start_addr.offset; return addr; } @@ -414,16 +413,11 @@ ftl_band_tail_md_addr(struct ftl_band *band) struct ftl_addr ftl_band_head_md_addr(struct ftl_band *band) { - struct ftl_addr addr = {}; - if (spdk_unlikely(!band->num_zones)) { return ftl_to_addr(FTL_ADDR_INVALID); } - addr.pu = CIRCLEQ_FIRST(&band->zones)->start_addr.pu; - addr.zone_id = band->id; - - return addr; + return CIRCLEQ_FIRST(&band->zones)->start_addr; } void @@ -511,23 +505,27 @@ ftl_band_user_lbks(const struct ftl_band *band) struct ftl_band * ftl_band_from_addr(struct spdk_ftl_dev *dev, struct ftl_addr addr) { - assert(addr.zone_id < ftl_get_num_bands(dev)); - return &dev->bands[addr.zone_id]; + size_t band_id = ftl_addr_get_band(dev, addr); + + assert(band_id < ftl_get_num_bands(dev)); + return &dev->bands[band_id]; } struct ftl_zone * ftl_band_zone_from_addr(struct ftl_band *band, struct ftl_addr addr) { - assert(addr.pu < ftl_get_num_punits(band->dev)); - return &band->zone_buf[addr.pu]; + size_t pu_id = ftl_addr_get_punit(band->dev, addr); + + assert(pu_id < ftl_get_num_punits(band->dev)); + return &band->zone_buf[pu_id]; } uint64_t ftl_band_lbkoff_from_addr(struct ftl_band *band, struct ftl_addr addr) { - assert(addr.zone_id == band->id); - assert(addr.pu < ftl_get_num_punits(band->dev)); - return addr.pu * ftl_get_num_blocks_in_zone(band->dev) + addr.offset; + assert(ftl_addr_get_band(band->dev, addr) == band->id); + assert(ftl_addr_get_punit(band->dev, addr) < ftl_get_num_punits(band->dev)); + return addr.offset % ftl_get_num_blocks_in_band(band->dev); } struct ftl_addr @@ -536,13 +534,15 @@ ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr, size_t num_ struct spdk_ftl_dev *dev = band->dev; struct ftl_zone *zone; size_t num_xfers, num_stripes; + uint64_t offset; - assert(addr.zone_id == band->id); + assert(ftl_addr_get_band(dev, addr) == band->id); + offset = ftl_addr_get_zone_offset(dev, addr); zone = ftl_band_zone_from_addr(band, addr); - num_lbks += (addr.offset % dev->xfer_size); - addr.offset -= (addr.offset % dev->xfer_size); + num_lbks += (offset % dev->xfer_size); + offset -= (offset % dev->xfer_size); #if defined(DEBUG) /* Check that the number of zones has not been changed */ @@ -557,10 +557,10 @@ ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr, size_t num_ #endif assert(band->num_zones != 0); num_stripes = (num_lbks / dev->xfer_size) / band->num_zones; - addr.offset += num_stripes * dev->xfer_size; + offset += num_stripes * dev->xfer_size; num_lbks -= num_stripes * dev->xfer_size * band->num_zones; - if (addr.offset > ftl_get_num_blocks_in_zone(dev)) { + if (offset > ftl_get_num_blocks_in_zone(dev)) { return ftl_to_addr(FTL_ADDR_INVALID); } @@ -569,26 +569,26 @@ ftl_band_next_xfer_addr(struct ftl_band *band, struct ftl_addr addr, size_t num_ /* When the last zone is reached the lbk part of the address */ /* needs to be increased by xfer_size */ if (ftl_band_zone_is_last(band, zone)) { - addr.offset += dev->xfer_size; - if (addr.offset > ftl_get_num_blocks_in_zone(dev)) { + offset += dev->xfer_size; + if (offset > ftl_get_num_blocks_in_zone(dev)) { return ftl_to_addr(FTL_ADDR_INVALID); } } zone = ftl_band_next_operational_zone(band, zone); assert(zone); - addr.pu = zone->start_addr.pu; num_lbks -= dev->xfer_size; } if (num_lbks) { - addr.offset += num_lbks; - if (addr.offset > ftl_get_num_blocks_in_zone(dev)) { + offset += num_lbks; + if (offset > ftl_get_num_blocks_in_zone(dev)) { return ftl_to_addr(FTL_ADDR_INVALID); } } + addr.offset = zone->start_addr.offset + offset; return addr; } @@ -597,12 +597,13 @@ ftl_xfer_offset_from_addr(struct ftl_band *band, struct ftl_addr addr) { struct ftl_zone *zone, *current_zone; unsigned int punit_offset = 0; - size_t off, num_stripes, xfer_size = band->dev->xfer_size; + size_t num_stripes, xfer_size = band->dev->xfer_size; + uint64_t offset; - assert(addr.zone_id == band->id); + assert(ftl_addr_get_band(band->dev, addr) == band->id); - num_stripes = (addr.offset / xfer_size) * band->num_zones; - off = addr.offset % xfer_size; + offset = ftl_addr_get_zone_offset(band->dev, addr); + num_stripes = (offset / xfer_size) * band->num_zones; current_zone = ftl_band_zone_from_addr(band, addr); CIRCLEQ_FOREACH(zone, &band->zones, circleq) { @@ -612,22 +613,15 @@ ftl_xfer_offset_from_addr(struct ftl_band *band, struct ftl_addr addr) punit_offset++; } - return xfer_size * (num_stripes + punit_offset) + off; + return xfer_size * (num_stripes + punit_offset) + offset % xfer_size; } struct ftl_addr ftl_band_addr_from_lbkoff(struct ftl_band *band, uint64_t lbkoff) { - struct ftl_addr addr = { .addr = 0 }; - struct spdk_ftl_dev *dev = band->dev; - uint64_t punit; - - punit = lbkoff / ftl_get_num_blocks_in_zone(dev); - - addr.offset = lbkoff % ftl_get_num_blocks_in_zone(dev); - addr.zone_id = band->id; - addr.pu = punit; + struct ftl_addr addr = { .offset = 0 }; + addr.offset = lbkoff + band->id * ftl_get_num_blocks_in_band(band->dev); return addr; } @@ -1055,7 +1049,7 @@ ftl_band_erase_cb(struct ftl_io *io, void *ctx, int status) } zone = ftl_band_zone_from_addr(io->band, io->addr); zone->state = SPDK_BDEV_ZONE_STATE_EMPTY; - zone->write_offset = 0; + zone->write_offset = zone->start_addr.offset; } int @@ -1122,7 +1116,7 @@ ftl_band_next_operational_zone(struct ftl_band *band, struct ftl_zone *zone) result = ftl_band_next_zone(band, zone); } else { CIRCLEQ_FOREACH_REVERSE(entry, &band->zones, circleq) { - if (entry->start_addr.pu > zone->start_addr.pu) { + if (entry->start_addr.offset > zone->start_addr.offset) { result = entry; } else { if (!result) { diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 4544bbba1..53f954db5 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -356,11 +356,10 @@ ftl_submit_erase(struct ftl_io *io) addr = zone->start_addr; } - assert(addr.offset == 0); + assert(ftl_addr_get_zone_offset(dev, addr) == 0); ftl_trace_submission(dev, io, addr, 1); - rc = spdk_bdev_zone_management(dev->base_bdev_desc, ioch->base_ioch, - ftl_block_offset_from_addr(dev, addr), + rc = spdk_bdev_zone_management(dev->base_bdev_desc, ioch->base_ioch, addr.offset, SPDK_BDEV_ZONE_RESET, ftl_io_cmpl_cb, io); if (spdk_unlikely(rc)) { ftl_io_fail(io, rc); @@ -590,8 +589,10 @@ ftl_wptr_advance(struct ftl_wptr *wptr, size_t xfer_size) assert(!ftl_addr_invalid(wptr->addr)); - SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "wptr: pu:%d zone:%d, lbk:%u\n", - wptr->addr.pu, wptr->addr.zone_id, wptr->addr.offset); + SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "wptr: pu:%lu band:%lu, offset:%lu\n", + ftl_addr_get_punit(dev, wptr->addr), + ftl_addr_get_band(dev, wptr->addr), + wptr->addr.offset); if (wptr->offset >= next_thld && !dev->next_band) { dev->next_band = ftl_next_write_band(dev); @@ -917,7 +918,7 @@ ftl_cache_read(struct ftl_io *io, uint64_t lba, pthread_spin_lock(&entry->lock); naddr = ftl_l2p_get(io->dev, lba); - if (addr.addr != naddr.addr) { + if (addr.offset != naddr.offset) { rc = -1; goto out; } @@ -938,7 +939,7 @@ ftl_read_next_logical_addr(struct ftl_io *io, struct ftl_addr *addr) *addr = ftl_l2p_get(dev, ftl_io_current_lba(io)); SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "Read addr:%lx, lba:%lu\n", - addr->addr, ftl_io_current_lba(io)); + addr->offset, ftl_io_current_lba(io)); /* If the address is invalid, skip it (the buffer should already be zero'ed) */ if (ftl_addr_invalid(*addr)) { @@ -961,8 +962,7 @@ ftl_read_next_logical_addr(struct ftl_io *io, struct ftl_addr *addr) break; } - if (ftl_block_offset_from_addr(dev, *addr) + i != - ftl_block_offset_from_addr(dev, next_addr)) { + if (addr->offset + i != next_addr.offset) { break; } } @@ -1010,7 +1010,7 @@ ftl_submit_read(struct ftl_io *io) ftl_trace_submission(dev, io, addr, lbk_cnt); rc = spdk_bdev_read_blocks(dev->base_bdev_desc, ioch->base_ioch, ftl_io_iovec_addr(io), - ftl_block_offset_from_addr(dev, addr), + addr.offset, lbk_cnt, ftl_io_cmpl_cb, io); if (spdk_unlikely(rc)) { if (rc == -ENOMEM) { @@ -1157,7 +1157,7 @@ ftl_nv_cache_submit_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) struct ftl_nv_cache *nv_cache = &io->dev->nv_cache; if (spdk_unlikely(!success)) { - SPDK_ERRLOG("Non-volatile cache write failed at %"PRIx64"\n", io->addr.addr); + SPDK_ERRLOG("Non-volatile cache write failed at %"PRIx64"\n", io->addr.offset); io->status = -EIO; } @@ -1184,14 +1184,14 @@ ftl_submit_nv_cache(void *ctx) thread = spdk_io_channel_get_thread(io->ioch); rc = spdk_bdev_write_blocks_with_md(nv_cache->bdev_desc, ioch->cache_ioch, - ftl_io_iovec_addr(io), io->md, io->addr.addr, + ftl_io_iovec_addr(io), io->md, io->addr.offset, io->lbk_cnt, ftl_nv_cache_submit_cb, io); if (rc == -ENOMEM) { spdk_thread_send_msg(thread, ftl_submit_nv_cache, io); return; } else if (rc) { SPDK_ERRLOG("Write to persistent cache failed: %s (%"PRIu64", %"PRIu64")\n", - spdk_strerror(-rc), io->addr.addr, io->lbk_cnt); + spdk_strerror(-rc), io->addr.offset, io->lbk_cnt); spdk_mempool_put(nv_cache->md_pool, io->md); io->status = -EIO; ftl_io_complete(io); @@ -1247,8 +1247,8 @@ _ftl_write_nv_cache(void *ctx) } /* Reserve area on the write buffer cache */ - child->addr.addr = ftl_reserve_nv_cache(&dev->nv_cache, &num_lbks, &phase); - if (child->addr.addr == FTL_LBA_INVALID) { + child->addr.offset = ftl_reserve_nv_cache(&dev->nv_cache, &num_lbks, &phase); + if (child->addr.offset == FTL_LBA_INVALID) { spdk_mempool_put(dev->nv_cache.md_pool, child->md); ftl_io_free(child); spdk_thread_send_msg(thread, _ftl_write_nv_cache, io); @@ -1371,7 +1371,7 @@ ftl_write_cb(struct ftl_io *io, void *arg, int status) } SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "Write addr:%lu, lba:%lu\n", - entry->addr.addr, entry->lba); + entry->addr.offset, entry->lba); } ftl_process_flush(dev, batch); @@ -1515,7 +1515,7 @@ ftl_submit_child_write(struct ftl_wptr *wptr, struct ftl_io *io, int lbk_cnt) addr = wptr->addr; } else { assert(io->flags & FTL_IO_DIRECT_ACCESS); - assert(io->addr.zone_id == wptr->band->id); + assert(ftl_addr_get_band(dev, io->addr) == wptr->band->id); addr = io->addr; } @@ -1530,14 +1530,14 @@ ftl_submit_child_write(struct ftl_wptr *wptr, struct ftl_io *io, int lbk_cnt) rc = spdk_bdev_write_blocks(dev->base_bdev_desc, ioch->base_ioch, ftl_io_iovec_addr(child), - ftl_block_offset_from_addr(dev, addr), + addr.offset, lbk_cnt, ftl_io_cmpl_cb, child); if (rc) { wptr->num_outstanding--; ftl_io_fail(child, rc); ftl_io_complete(child); SPDK_ERRLOG("spdk_bdev_write_blocks_with_md failed with status:%d, addr:%lu\n", - rc, addr.addr); + rc, addr.offset); return -EIO; } @@ -1687,8 +1687,7 @@ ftl_wptr_process_writes(struct ftl_wptr *wptr) addr = ftl_band_next_addr(wptr->band, addr, 1); } - SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "Write addr:%lx, %lx\n", wptr->addr.addr, - ftl_block_offset_from_addr(dev, wptr->addr)); + SPDK_DEBUGLOG(SPDK_LOG_FTL_CORE, "Write addr:%lx\n", wptr->addr.offset); if (ftl_submit_write(wptr, io)) { /* TODO: we need some recovery here */ diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index c60dafc06..bb6625ff4 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -279,10 +279,10 @@ struct spdk_io_channel * ftl_get_io_channel(const struct spdk_ftl_dev *dev); #define ftl_to_addr(address) \ - (struct ftl_addr) { .addr = (uint64_t)(address) } + (struct ftl_addr) { .offset = (uint64_t)(address) } #define ftl_to_addr_packed(address) \ - (struct ftl_addr) { .pack.addr = (uint32_t)(address) } + (struct ftl_addr) { .pack.offset = (uint32_t)(address) } static inline struct spdk_thread * ftl_get_core_thread(const struct spdk_ftl_dev *dev) @@ -326,6 +326,24 @@ ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev) return ftl_get_num_punits(dev) * ftl_get_num_blocks_in_zone(dev); } +static inline uint64_t +ftl_addr_get_band(const struct spdk_ftl_dev *dev, struct ftl_addr addr) +{ + return addr.offset / ftl_get_num_blocks_in_band(dev); +} + +static inline uint64_t +ftl_addr_get_punit(const struct spdk_ftl_dev *dev, struct ftl_addr addr) +{ + return (addr.offset / ftl_get_num_blocks_in_zone(dev)) % ftl_get_num_punits(dev); +} + +static inline uint64_t +ftl_addr_get_zone_offset(const struct spdk_ftl_dev *dev, struct ftl_addr addr) +{ + return addr.offset % ftl_get_num_blocks_in_zone(dev); +} + static inline size_t ftl_vld_map_size(const struct spdk_ftl_dev *dev) { @@ -341,7 +359,7 @@ ftl_addr_packed(const struct spdk_ftl_dev *dev) static inline int ftl_addr_invalid(struct ftl_addr addr) { - return addr.addr == ftl_to_addr(FTL_ADDR_INVALID).addr; + return addr.offset == ftl_to_addr(FTL_ADDR_INVALID).offset; } static inline int @@ -350,27 +368,6 @@ ftl_addr_cached(struct ftl_addr addr) return !ftl_addr_invalid(addr) && addr.cached; } -static inline struct ftl_addr -ftl_addr_from_block_offset(const struct spdk_ftl_dev *dev, uint64_t offset) -{ - struct ftl_addr addr = {}; - uint64_t zone_num; - - addr.offset = offset % ftl_get_num_blocks_in_zone(dev); - zone_num = offset / ftl_get_num_blocks_in_zone(dev); - addr.pu = zone_num % ftl_get_num_punits(dev); - addr.zone_id = zone_num / ftl_get_num_punits(dev); - - return addr; -} - -static inline uint64_t -ftl_block_offset_from_addr(const struct spdk_ftl_dev *dev, struct ftl_addr addr) -{ - return (addr.zone_id * ftl_get_num_punits(dev) + addr.pu) * - ftl_get_num_blocks_in_zone(dev) + addr.offset; -} - static inline struct ftl_addr ftl_addr_to_packed(const struct spdk_ftl_dev *dev, struct ftl_addr addr) { @@ -382,7 +379,7 @@ ftl_addr_to_packed(const struct spdk_ftl_dev *dev, struct ftl_addr addr) p.pack.cached = 1; p.pack.cache_offset = (uint32_t) addr.cache_offset; } else { - p.pack.addr = (uint32_t) ftl_block_offset_from_addr(dev, addr); + p.pack.offset = (uint32_t) addr.offset; } return p; @@ -393,13 +390,13 @@ ftl_addr_from_packed(const struct spdk_ftl_dev *dev, struct ftl_addr p) { struct ftl_addr addr = {}; - if (p.pack.addr == (uint32_t)FTL_ADDR_INVALID) { + if (p.pack.offset == (uint32_t)FTL_ADDR_INVALID) { addr = ftl_to_addr(FTL_ADDR_INVALID); } else if (p.pack.cached) { addr.cached = 1; addr.cache_offset = p.pack.cache_offset; } else { - addr = ftl_addr_from_block_offset(dev, p.pack.addr); + addr = p; } return addr; @@ -424,7 +421,7 @@ ftl_addr_from_packed(const struct spdk_ftl_dev *dev, struct ftl_addr p) _ftl_l2p_get(l2p, off, 64) #define ftl_addr_cmp(p1, p2) \ - ((p1).addr == (p2).addr) + ((p1).offset == (p2).offset) static inline void ftl_l2p_set(struct spdk_ftl_dev *dev, uint64_t lba, struct ftl_addr addr) @@ -432,9 +429,9 @@ ftl_l2p_set(struct spdk_ftl_dev *dev, uint64_t lba, struct ftl_addr addr) assert(dev->num_lbas > lba); if (ftl_addr_packed(dev)) { - _ftl_l2p_set32(dev->l2p, lba, ftl_addr_to_packed(dev, addr).addr); + _ftl_l2p_set32(dev->l2p, lba, ftl_addr_to_packed(dev, addr).offset); } else { - _ftl_l2p_set64(dev->l2p, lba, addr.addr); + _ftl_l2p_set64(dev->l2p, lba, addr.offset); } } @@ -450,6 +447,7 @@ ftl_l2p_get(struct spdk_ftl_dev *dev, uint64_t lba) return ftl_to_addr(_ftl_l2p_get64(dev->l2p, lba)); } } + static inline bool ftl_dev_has_nv_cache(const struct spdk_ftl_dev *dev) { diff --git a/lib/ftl/ftl_debug.c b/lib/ftl/ftl_debug.c index aaad26ce5..110f40789 100644 --- a/lib/ftl/ftl_debug.c +++ b/lib/ftl/ftl_debug.c @@ -79,7 +79,7 @@ ftl_band_validate_md(struct ftl_band *band) continue; } - if (addr_l2p.addr != addr_md.addr) { + if (addr_l2p.offset != addr_md.offset) { valid = false; break; } diff --git a/lib/ftl/ftl_debug.h b/lib/ftl/ftl_debug.h index 22f01942f..15d43fae8 100644 --- a/lib/ftl/ftl_debug.h +++ b/lib/ftl/ftl_debug.h @@ -53,8 +53,7 @@ static inline const char * ftl_addr2str(struct ftl_addr addr, char *buf, size_t size) { - snprintf(buf, size, "(pu: %u, chk: %u, lbk: %u)", - addr.pu, addr.zone_id, addr.offset); + snprintf(buf, size, "(%"PRIu64")", addr.offset); return buf; } diff --git a/lib/ftl/ftl_init.c b/lib/ftl/ftl_init.c index 4ff430667..005f60a53 100644 --- a/lib/ftl/ftl_init.c +++ b/lib/ftl/ftl_init.c @@ -819,13 +819,12 @@ ftl_dev_get_zone_info_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar num_zones = spdk_min(zones_left, FTL_ZONE_INFO_COUNT); for (i = 0; i < num_zones; ++i) { - addr = ftl_addr_from_block_offset(dev, init_ctx->info[i].zone_id); - band = &dev->bands[addr.zone_id]; - zone = &band->zone_buf[addr.pu]; + addr.offset = init_ctx->info[i].zone_id; + band = &dev->bands[ftl_addr_get_band(dev, addr)]; + zone = &band->zone_buf[ftl_addr_get_punit(dev, addr)]; zone->state = init_ctx->info[i].state; zone->start_addr = addr; - addr = ftl_addr_from_block_offset(dev, init_ctx->info[i].write_pointer); - zone->write_offset = addr.offset; + zone->write_offset = init_ctx->info[i].write_pointer; /* TODO: add support for zone capacity less than zone size */ if (init_ctx->info[i].capacity != ftl_get_num_blocks_in_zone(dev)) { diff --git a/lib/ftl/ftl_io.c b/lib/ftl/ftl_io.c index 125ea09a1..797d70dfd 100644 --- a/lib/ftl/ftl_io.c +++ b/lib/ftl/ftl_io.c @@ -263,7 +263,7 @@ ftl_io_init(struct ftl_io *io, struct spdk_ftl_dev *dev, io->type = type; io->dev = dev; io->lba.single = FTL_LBA_INVALID; - io->addr.addr = FTL_ADDR_INVALID; + io->addr.offset = FTL_ADDR_INVALID; io->cb_fn = fn; io->cb_ctx = ctx; io->trace = ftl_trace_alloc_id(dev); diff --git a/lib/ftl/ftl_restore.c b/lib/ftl/ftl_restore.c index 5cdd8a1ce..b00c8a88a 100644 --- a/lib/ftl/ftl_restore.c +++ b/lib/ftl/ftl_restore.c @@ -1156,6 +1156,7 @@ ftl_pad_zone_cb(struct ftl_io *io, void *arg, int status) struct ftl_band *band = io->band; struct ftl_zone *zone; struct ftl_io *new_io; + uint64_t offset; restore->num_ios--; /* TODO check for next unit error vs early close error */ @@ -1164,7 +1165,8 @@ ftl_pad_zone_cb(struct ftl_io *io, void *arg, int status) goto end; } - if (io->addr.offset + io->lbk_cnt == ftl_get_num_blocks_in_zone(restore->dev)) { + offset = io->addr.offset % ftl_get_num_blocks_in_zone(restore->dev); + if (offset + io->lbk_cnt == ftl_get_num_blocks_in_zone(restore->dev)) { zone = ftl_band_zone_from_addr(band, io->addr); zone->state = SPDK_BDEV_ZONE_STATE_CLOSED; } else { diff --git a/lib/ftl/ftl_trace.c b/lib/ftl/ftl_trace.c index b02828b2e..9794a6f9c 100644 --- a/lib/ftl/ftl_trace.c +++ b/lib/ftl/ftl_trace.c @@ -249,7 +249,7 @@ ftl_trace_rwb_pop(struct spdk_ftl_dev *dev, const struct ftl_rwb_entry *entry) tpoint_id = FTL_TRACE_RWB_POP(FTL_TRACE_SOURCE_USER); } - spdk_trace_record(tpoint_id, entry->trace, 0, entry->addr.addr, entry->lba); + spdk_trace_record(tpoint_id, entry->trace, 0, entry->addr.offset, entry->lba); } void @@ -337,7 +337,7 @@ ftl_trace_submission(struct spdk_ftl_dev *dev, const struct ftl_io *io, struct f } } - spdk_trace_record(tpoint_id, io->trace, addr_cnt, 0, addr.addr); + spdk_trace_record(tpoint_id, io->trace, addr_cnt, 0, addr.offset); } void diff --git a/test/unit/lib/ftl/common/utils.c b/test/unit/lib/ftl/common/utils.c index e079aaeb5..ddf123488 100644 --- a/test/unit/lib/ftl/common/utils.c +++ b/test/unit/lib/ftl/common/utils.c @@ -46,7 +46,7 @@ struct base_bdev_geometry { extern struct base_bdev_geometry g_geo; struct spdk_ftl_dev *test_init_ftl_dev(const struct base_bdev_geometry *geo); -struct ftl_band *test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id); +struct ftl_band *test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id, size_t zone_size); void test_free_ftl_dev(struct spdk_ftl_dev *dev); void test_free_ftl_band(struct ftl_band *band); uint64_t test_offset_from_addr(struct ftl_addr addr, struct ftl_band *band); @@ -94,7 +94,7 @@ test_init_ftl_dev(const struct base_bdev_geometry *geo) } struct ftl_band * -test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id) +test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id, size_t zone_size) { struct ftl_band *band; struct ftl_zone *zone; @@ -122,8 +122,7 @@ test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id) for (size_t i = 0; i < ftl_get_num_punits(dev); ++i) { zone = &band->zone_buf[i]; zone->state = SPDK_BDEV_ZONE_STATE_CLOSED; - zone->start_addr.pu = i; - zone->start_addr.zone_id = band->id; + zone->start_addr.offset = zone_size * (id * ftl_get_num_punits(dev) + i); CIRCLEQ_INSERT_TAIL(&band->zones, zone, circleq); band->num_zones++; } @@ -160,7 +159,7 @@ test_offset_from_addr(struct ftl_addr addr, struct ftl_band *band) { struct spdk_ftl_dev *dev = band->dev; - CU_ASSERT_EQUAL(addr.zone_id, band->id); + CU_ASSERT_EQUAL(ftl_addr_get_band(dev, addr), band->id); - return addr.pu * ftl_get_num_blocks_in_zone(dev) + addr.offset; + return addr.offset - band->id * ftl_get_num_blocks_in_band(dev); } diff --git a/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c b/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c index 96ed9e5c8..6bfd237a4 100644 --- a/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c +++ b/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c @@ -59,7 +59,7 @@ setup_band(void) int rc; g_dev = test_init_ftl_dev(&g_geo); - g_band = test_init_ftl_band(g_dev, TEST_BAND_IDX); + g_band = test_init_ftl_band(g_dev, TEST_BAND_IDX, g_geo.zone_size); rc = ftl_band_alloc_lba_map(g_band); CU_ASSERT_EQUAL_FATAL(rc, 0); } @@ -76,7 +76,7 @@ addr_from_punit(uint64_t punit) { struct ftl_addr addr = {}; - addr.pu = punit; + addr.offset = punit * g_geo.zone_size; return addr; } @@ -89,7 +89,7 @@ test_band_lbkoff_from_addr_base(void) setup_band(); for (i = 0; i < ftl_get_num_punits(g_dev); ++i) { addr = addr_from_punit(i); - addr.zone_id = TEST_BAND_IDX; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); offset = ftl_band_lbkoff_from_addr(g_band, addr); CU_ASSERT_EQUAL(offset, flat_lun * ftl_get_num_blocks_in_zone(g_dev)); @@ -108,8 +108,7 @@ test_band_lbkoff_from_addr_offset(void) for (i = 0; i < ftl_get_num_punits(g_dev); ++i) { for (j = 0; j < g_geo.zone_size; ++j) { addr = addr_from_punit(i); - addr.zone_id = TEST_BAND_IDX; - addr.offset = j; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev) + j; offset = ftl_band_lbkoff_from_addr(g_band, addr); @@ -130,13 +129,12 @@ test_band_addr_from_lbkoff(void) for (i = 0; i < ftl_get_num_punits(g_dev); ++i) { for (j = 0; j < g_geo.zone_size; ++j) { expect = addr_from_punit(i); - expect.zone_id = TEST_BAND_IDX; - expect.offset = j; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev) + j; offset = ftl_band_lbkoff_from_addr(g_band, expect); addr = ftl_band_addr_from_lbkoff(g_band, offset); - CU_ASSERT_EQUAL(addr.addr, expect.addr); + CU_ASSERT_EQUAL(addr.offset, expect.offset); } } cleanup_band(); @@ -152,7 +150,7 @@ test_band_set_addr(void) setup_band(); lba_map = &g_band->lba_map; addr = addr_from_punit(0); - addr.zone_id = TEST_BAND_IDX; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); CU_ASSERT_EQUAL(lba_map->num_vld, 0); @@ -163,13 +161,13 @@ test_band_set_addr(void) CU_ASSERT_EQUAL(lba_map->map[offset], TEST_LBA); CU_ASSERT_TRUE(spdk_bit_array_get(lba_map->vld, offset)); - addr.pu++; + addr.offset += g_geo.zone_size; offset = test_offset_from_addr(addr, g_band); ftl_band_set_addr(g_band, TEST_LBA + 1, addr); CU_ASSERT_EQUAL(lba_map->num_vld, 2); CU_ASSERT_EQUAL(lba_map->map[offset], TEST_LBA + 1); CU_ASSERT_TRUE(spdk_bit_array_get(lba_map->vld, offset)); - addr.pu--; + addr.offset -= g_geo.zone_size; offset = test_offset_from_addr(addr, g_band); CU_ASSERT_TRUE(spdk_bit_array_get(lba_map->vld, offset)); cleanup_band(); @@ -185,7 +183,7 @@ test_invalidate_addr(void) setup_band(); lba_map = &g_band->lba_map; addr = addr_from_punit(0); - addr.zone_id = TEST_BAND_IDX; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); offset[0] = test_offset_from_addr(addr, g_band); ftl_band_set_addr(g_band, TEST_LBA, addr); @@ -197,7 +195,7 @@ test_invalidate_addr(void) offset[0] = test_offset_from_addr(addr, g_band); ftl_band_set_addr(g_band, TEST_LBA, addr); - addr.pu++; + addr.offset += g_geo.zone_size; offset[1] = test_offset_from_addr(addr, g_band); ftl_band_set_addr(g_band, TEST_LBA + 1, addr); CU_ASSERT_EQUAL(lba_map->num_vld, 2); @@ -218,69 +216,66 @@ test_next_xfer_addr(void) setup_band(); /* Verify simple one lbk incremention */ addr = addr_from_punit(0); - addr.zone_id = TEST_BAND_IDX; - addr.offset = 0; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); expect = addr; - expect.offset = 1; + expect.offset += 1; result = ftl_band_next_xfer_addr(g_band, addr, 1); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Verify jumping between zones */ expect = addr_from_punit(1); - expect.zone_id = TEST_BAND_IDX; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); result = ftl_band_next_xfer_addr(g_band, addr, g_dev->xfer_size); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Verify jumping works with unaligned offsets */ expect = addr_from_punit(1); - expect.zone_id = TEST_BAND_IDX; - expect.offset = 3; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev) + 3; result = ftl_band_next_xfer_addr(g_band, addr, g_dev->xfer_size + 3); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Verify jumping from last zone to the first one */ expect = addr_from_punit(0); - expect.zone_id = TEST_BAND_IDX; - expect.offset = g_dev->xfer_size; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev) + g_dev->xfer_size; addr = addr_from_punit(ftl_get_num_punits(g_dev) - 1); - addr.zone_id = TEST_BAND_IDX; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); result = ftl_band_next_xfer_addr(g_band, addr, g_dev->xfer_size); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Verify jumping from last zone to the first one with unaligned offset */ expect = addr_from_punit(0); - expect.zone_id = TEST_BAND_IDX; - expect.offset = g_dev->xfer_size + 2; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); + expect.offset += g_dev->xfer_size + 2; addr = addr_from_punit(ftl_get_num_punits(g_dev) - 1); - addr.zone_id = TEST_BAND_IDX; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); result = ftl_band_next_xfer_addr(g_band, addr, g_dev->xfer_size + 2); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Verify large offset spanning across the whole band multiple times */ expect = addr_from_punit(0); - expect.zone_id = TEST_BAND_IDX; - expect.offset = g_dev->xfer_size * 5 + 4; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); + expect.offset += g_dev->xfer_size * 5 + 4; addr = addr_from_punit(0); - addr.zone_id = TEST_BAND_IDX; - addr.offset = g_dev->xfer_size * 2 + 1; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); + addr.offset += g_dev->xfer_size * 2 + 1; result = ftl_band_next_xfer_addr(g_band, addr, 3 * g_dev->xfer_size * ftl_get_num_punits(g_dev) + 3); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); /* Remove one zone and verify it's skipped properly */ g_band->zone_buf[1].state = SPDK_BDEV_ZONE_STATE_OFFLINE; CIRCLEQ_REMOVE(&g_band->zones, &g_band->zone_buf[1], circleq); g_band->num_zones--; expect = addr_from_punit(2); - expect.zone_id = TEST_BAND_IDX; - expect.offset = g_dev->xfer_size * 5 + 4; + expect.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); + expect.offset += g_dev->xfer_size * 5 + 4; addr = addr_from_punit(0); - addr.zone_id = TEST_BAND_IDX; - addr.offset = g_dev->xfer_size * 2 + 1; + addr.offset += TEST_BAND_IDX * ftl_get_num_blocks_in_band(g_dev); + addr.offset += g_dev->xfer_size * 2 + 1; result = ftl_band_next_xfer_addr(g_band, addr, 3 * g_dev->xfer_size * (ftl_get_num_punits(g_dev) - 1) + g_dev->xfer_size + 3); - CU_ASSERT_EQUAL(result.addr, expect.addr); + CU_ASSERT_EQUAL(result.offset, expect.offset); cleanup_band(); } diff --git a/test/unit/lib/ftl/ftl_md/ftl_md_ut.c b/test/unit/lib/ftl/ftl_md/ftl_md_ut.c index 668b1481c..18c6f1c31 100644 --- a/test/unit/lib/ftl/ftl_md/ftl_md_ut.c +++ b/test/unit/lib/ftl/ftl_md/ftl_md_ut.c @@ -53,7 +53,7 @@ setup_band(struct ftl_band **band, const struct base_bdev_geometry *geo) struct spdk_ftl_dev *dev; dev = test_init_ftl_dev(&g_geo); - *band = test_init_ftl_band(dev, 0); + *band = test_init_ftl_band(dev, 0, geo->zone_size); rc = ftl_band_alloc_lba_map(*band); SPDK_CU_ASSERT_FATAL(rc == 0); (*band)->state = FTL_BAND_STATE_PREP; diff --git a/test/unit/lib/ftl/ftl_ppa/ftl_ppa_ut.c b/test/unit/lib/ftl/ftl_ppa/ftl_ppa_ut.c index 95d9632c0..4b03cebd3 100644 --- a/test/unit/lib/ftl/ftl_ppa/ftl_ppa_ut.c +++ b/test/unit/lib/ftl/ftl_ppa/ftl_ppa_ut.c @@ -118,19 +118,17 @@ test_addr_pack32(void) /* Check valid address transformation */ orig.offset = 4; - orig.zone_id = 3; - orig.pu = 2; addr = ftl_addr_to_packed(g_dev, orig); - CU_ASSERT_TRUE(addr.addr <= UINT32_MAX); + CU_ASSERT_TRUE(addr.offset <= UINT32_MAX); CU_ASSERT_FALSE(addr.pack.cached); addr = ftl_addr_from_packed(g_dev, addr); CU_ASSERT_FALSE(ftl_addr_invalid(addr)); - CU_ASSERT_EQUAL(addr.addr, orig.addr); + CU_ASSERT_EQUAL(addr.offset, orig.offset); /* Check invalid address transformation */ orig = ftl_to_addr(FTL_ADDR_INVALID); addr = ftl_addr_to_packed(g_dev, orig); - CU_ASSERT_TRUE(addr.addr <= UINT32_MAX); + CU_ASSERT_TRUE(addr.offset <= UINT32_MAX); addr = ftl_addr_from_packed(g_dev, addr); CU_ASSERT_TRUE(ftl_addr_invalid(addr)); @@ -138,48 +136,12 @@ test_addr_pack32(void) orig.cached = 1; orig.cache_offset = 1024; addr = ftl_addr_to_packed(g_dev, orig); - CU_ASSERT_TRUE(addr.addr <= UINT32_MAX); + CU_ASSERT_TRUE(addr.offset <= UINT32_MAX); CU_ASSERT_TRUE(addr.pack.cached); addr = ftl_addr_from_packed(g_dev, addr); CU_ASSERT_FALSE(ftl_addr_invalid(addr)); CU_ASSERT_TRUE(ftl_addr_cached(addr)); - CU_ASSERT_EQUAL(addr.addr, orig.addr); - clean_l2p(); -} - -static void -test_addr_pack64(void) -{ - struct ftl_addr orig = {}, addr; - - orig.offset = 4; - orig.zone_id = 3; - orig.pu = 2; - - /* Check valid address transformation */ - addr.addr = ftl_block_offset_from_addr(g_dev, orig); - addr = ftl_addr_from_block_offset(g_dev, addr.addr); - CU_ASSERT_FALSE(ftl_addr_invalid(addr)); - CU_ASSERT_EQUAL(addr.addr, orig.addr); - - orig.offset = 0x7ea0be0f; - orig.zone_id = 0x6; - orig.pu = 0x4; - - addr.addr = ftl_block_offset_from_addr(g_dev, orig); - addr = ftl_addr_from_block_offset(g_dev, addr.addr); - CU_ASSERT_FALSE(ftl_addr_invalid(addr)); - CU_ASSERT_EQUAL(addr.addr, orig.addr); - - /* Check maximum valid address */ - orig.offset = 0xffffffff; - orig.zone_id = 0xf; - orig.pu = 0x7; - - addr.addr = ftl_block_offset_from_addr(g_dev, orig); - addr = ftl_addr_from_block_offset(g_dev, addr.addr); - CU_ASSERT_FALSE(ftl_addr_invalid(addr)); - CU_ASSERT_EQUAL(addr.addr, orig.addr); + CU_ASSERT_EQUAL(addr.offset, orig.offset); clean_l2p(); } @@ -267,8 +229,6 @@ main(int argc, char **argv) test_addr_invalid) == NULL || CU_add_test(suite64, "test_addr64_cached", test_addr_cached) == NULL - || CU_add_test(suite64, "test_addr64_pack", - test_addr_pack64) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c index 1c3e0aa6e..165ce5bf5 100644 --- a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c +++ b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c @@ -105,16 +105,9 @@ ftl_band_lbkoff_from_addr(struct ftl_band *band, struct ftl_addr addr) struct ftl_addr ftl_band_addr_from_lbkoff(struct ftl_band *band, uint64_t lbkoff) { - struct ftl_addr addr = { .addr = 0 }; - struct spdk_ftl_dev *dev = band->dev; - uint64_t punit; - - punit = lbkoff / ftl_get_num_blocks_in_zone(dev); - - addr.offset = lbkoff % ftl_get_num_blocks_in_zone(dev); - addr.zone_id = band->id; - addr.pu = punit; + struct ftl_addr addr = {}; + addr.offset = lbkoff + band->id * ftl_get_num_blocks_in_band(band->dev); return addr; } @@ -211,7 +204,7 @@ setup_reloc(struct spdk_ftl_dev **_dev, struct ftl_reloc **_reloc, SPDK_CU_ASSERT_FATAL(ftl_get_num_bands(dev) > 0); for (i = 0; i < ftl_get_num_bands(dev); ++i) { - test_init_ftl_band(dev, i); + test_init_ftl_band(dev, i, geo->zone_size); } reloc = ftl_reloc_init(dev); diff --git a/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c b/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c index a7e923d4b..ba7f97f4f 100644 --- a/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c +++ b/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c @@ -109,7 +109,7 @@ setup_wptr_test(struct spdk_ftl_dev **dev, const struct base_bdev_geometry *geo) t_dev = test_init_ftl_dev(geo); for (i = 0; i < ftl_get_num_bands(t_dev); ++i) { - test_init_ftl_band(t_dev, i); + test_init_ftl_band(t_dev, i, geo->zone_size); t_dev->bands[i].state = FTL_BAND_STATE_CLOSED; ftl_band_set_state(&t_dev->bands[i], FTL_BAND_STATE_FREE); } @@ -155,7 +155,6 @@ test_wptr(void) for (lbk = 0, offset = 0; lbk < ftl_get_num_blocks_in_zone(dev) / xfer_size; ++lbk) { for (zone = 0; zone < band->num_zones; ++zone) { - CU_ASSERT_EQUAL(wptr->addr.offset, (lbk * xfer_size)); CU_ASSERT_EQUAL(wptr->offset, offset); ftl_wptr_advance(wptr, xfer_size); offset += xfer_size; @@ -163,7 +162,6 @@ test_wptr(void) } CU_ASSERT_EQUAL(band->state, FTL_BAND_STATE_FULL); - CU_ASSERT_EQUAL(wptr->addr.offset, ftl_get_num_blocks_in_zone(dev)); ftl_band_set_state(band, FTL_BAND_STATE_CLOSING);