diff --git a/lib/ftl/ftl_nv_cache.c b/lib/ftl/ftl_nv_cache.c index 1cb04f8d7..7b616755b 100644 --- a/lib/ftl/ftl_nv_cache.c +++ b/lib/ftl/ftl_nv_cache.c @@ -709,7 +709,7 @@ compaction_process(struct ftl_nv_cache_compactor *compactor) struct spdk_ftl_dev *dev = SPDK_CONTAINEROF(nv_cache, struct spdk_ftl_dev, nv_cache); struct ftl_nv_cache_chunk *chunk; - uint64_t to_read, addr; + uint64_t to_read, addr, begin, end, offset; int rc; /* Check if all read blocks done */ @@ -733,8 +733,34 @@ compaction_process(struct ftl_nv_cache_compactor *compactor) /* * Get range of blocks to read */ + to_read = chunk_blocks_to_read(chunk); + assert(to_read > 0); + addr = ftl_addr_from_nvc_offset(dev, chunk->offset + chunk->md->read_pointer); - to_read = spdk_min(chunk_blocks_to_read(chunk), compactor->rd->num_blocks); + begin = ftl_bitmap_find_first_set(dev->valid_map, addr, addr + to_read); + if (begin != UINT64_MAX) { + offset = spdk_min(begin - addr, to_read); + } else { + offset = to_read; + } + + if (offset) { + chunk->md->read_pointer += offset; + chunk_compaction_advance(chunk, offset); + to_read -= offset; + if (!to_read) { + compactor_deactivate(compactor); + return; + } + } + + end = ftl_bitmap_find_first_clear(dev->valid_map, begin + 1, begin + to_read); + if (end != UINT64_MAX) { + to_read = end - begin; + } + + addr = begin; + to_read = spdk_min(to_read, compactor->rd->num_blocks); /* Read data and metadata from NV cache */ rc = compaction_submit_read(compactor, addr, to_read); diff --git a/lib/ftl/ftl_reloc.c b/lib/ftl/ftl_reloc.c index 04455f3cf..a2381639a 100644 --- a/lib/ftl/ftl_reloc.c +++ b/lib/ftl/ftl_reloc.c @@ -372,11 +372,49 @@ static void move_read(struct ftl_reloc *reloc, struct ftl_reloc_move *mv, struct ftl_band *band) { struct ftl_rq *rq = mv->rq; - uint64_t band_left, rq_left; + uint64_t blocks = ftl_get_num_blocks_in_band(band->dev); + uint64_t pos = band->md->iter.offset; + uint64_t begin = ftl_bitmap_find_first_set(band->p2l_map.valid, pos, UINT64_MAX); + uint64_t end, band_left, rq_left; + + if (spdk_likely(begin < blocks)) { + if (begin > pos) { + ftl_band_iter_advance(band, begin - pos); + } else if (begin == pos) { + /* Valid block at the position of iterator */ + } else { + /* Inconsistent state */ + ftl_abort(); + } + } else if (UINT64_MAX == begin) { + /* No more valid LBAs in the band */ + band_left = ftl_band_user_blocks_left(band, pos); + ftl_band_iter_advance(band, band_left); + + assert(ftl_band_filled(band, band->md->iter.offset)); + + if (rq->iter.idx) { + move_rq_pad(rq, band); + move_set_state(mv, FTL_RELOC_STATE_WAIT); + rq->iter.qd++; + rq->owner.cb(rq); + } + + return; + } else { + /* Inconsistent state */ + ftl_abort(); + } rq_left = rq->num_blocks - rq->iter.idx; assert(rq_left > 0); + /* Find next clear bit, but no further than max request count */ + end = ftl_bitmap_find_first_clear(band->p2l_map.valid, begin + 1, begin + rq_left); + if (end != UINT64_MAX) { + rq_left = end - begin; + } + band_left = ftl_band_user_blocks_left(band, band->md->iter.offset); rq->iter.count = spdk_min(rq_left, band_left);