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 <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468701
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Wojciech Malikowski 2019-09-20 07:26:16 -04:00 committed by Tomasz Zawadzki
parent 59acbc91c2
commit d6234332fb
16 changed files with 149 additions and 220 deletions

View File

@ -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;
};
};

View File

@ -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) {

View File

@ -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 */

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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);