lib/ftl: Media management events

Adding support for handling media management events.

Change-Id: I1b87143ddd360e314385e8dc70359aeb0d526b5a
Signed-off-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481691
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
Wojciech Malikowski 2020-01-14 05:15:41 -05:00 committed by Jim Harris
parent 4d122a3559
commit 82b7b4aad5
3 changed files with 109 additions and 0 deletions

View File

@ -2157,6 +2157,69 @@ ftl_addr_is_written(struct ftl_band *band, struct ftl_addr addr)
return addr.offset < zone->info.write_pointer; return addr.offset < zone->info.write_pointer;
} }
static void ftl_process_media_event(struct spdk_ftl_dev *dev, struct spdk_bdev_media_event event);
static void
_ftl_process_media_event(void *ctx)
{
struct ftl_media_event *event = ctx;
struct spdk_ftl_dev *dev = event->dev;
ftl_process_media_event(dev, event->event);
spdk_mempool_put(dev->media_events_pool, event);
}
static void
ftl_process_media_event(struct spdk_ftl_dev *dev, struct spdk_bdev_media_event event)
{
struct ftl_band *band;
struct ftl_addr addr = { .offset = event.offset };
size_t block_off;
if (!ftl_check_core_thread(dev)) {
struct ftl_media_event *media_event;
media_event = spdk_mempool_get(dev->media_events_pool);
if (!media_event) {
SPDK_ERRLOG("Media event lost due to lack of memory");
return;
}
media_event->dev = dev;
media_event->event = event;
spdk_thread_send_msg(ftl_get_core_thread(dev), _ftl_process_media_event,
media_event);
return;
}
band = ftl_band_from_addr(dev, addr);
block_off = ftl_band_block_offset_from_addr(band, addr);
ftl_reloc_add(dev->reloc, band, block_off, event.num_blocks, 0, false);
}
void
ftl_get_media_events(struct spdk_ftl_dev *dev)
{
#define FTL_MAX_MEDIA_EVENTS 128
struct spdk_bdev_media_event events[FTL_MAX_MEDIA_EVENTS];
size_t num_events, i;
if (!dev->initialized) {
return;
}
do {
num_events = spdk_bdev_get_media_events(dev->base_bdev_desc,
events, FTL_MAX_MEDIA_EVENTS);
for (i = 0; i < num_events; ++i) {
ftl_process_media_event(dev, events[i]);
}
} while (num_events);
}
static void static void
ftl_process_retry_queue(struct spdk_ftl_dev *dev) ftl_process_retry_queue(struct spdk_ftl_dev *dev)
{ {

View File

@ -167,6 +167,9 @@ struct spdk_ftl_dev {
/* LBA map requests pool */ /* LBA map requests pool */
struct spdk_mempool *lba_request_pool; struct spdk_mempool *lba_request_pool;
/* Media management events pool */
struct spdk_mempool *media_events_pool;
/* Statistics */ /* Statistics */
struct ftl_stats stats; struct ftl_stats stats;
@ -247,6 +250,13 @@ struct ftl_nv_cache_header {
uint32_t checksum; uint32_t checksum;
} __attribute__((packed)); } __attribute__((packed));
struct ftl_media_event {
/* Owner */
struct spdk_ftl_dev *dev;
/* Media event */
struct spdk_bdev_media_event event;
};
typedef void (*ftl_restore_fn)(struct spdk_ftl_dev *, struct ftl_restore *, int); typedef void (*ftl_restore_fn)(struct spdk_ftl_dev *, struct ftl_restore *, int);
void ftl_apply_limits(struct spdk_ftl_dev *dev); void ftl_apply_limits(struct spdk_ftl_dev *dev);
@ -274,6 +284,7 @@ int ftl_nv_cache_write_header(struct ftl_nv_cache *nv_cache, bool shutdown,
spdk_bdev_io_completion_cb cb_fn, void *cb_arg); spdk_bdev_io_completion_cb cb_fn, void *cb_arg);
int ftl_nv_cache_scrub(struct ftl_nv_cache *nv_cache, spdk_bdev_io_completion_cb cb_fn, int ftl_nv_cache_scrub(struct ftl_nv_cache *nv_cache, spdk_bdev_io_completion_cb cb_fn,
void *cb_arg); void *cb_arg);
void ftl_get_media_events(struct spdk_ftl_dev *dev);
struct spdk_io_channel * struct spdk_io_channel *
ftl_get_io_channel(const struct spdk_ftl_dev *dev); ftl_get_io_channel(const struct spdk_ftl_dev *dev);

View File

@ -216,10 +216,15 @@ ftl_dev_init_bands(struct spdk_ftl_dev *dev)
static void static void
ftl_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) ftl_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
{ {
struct spdk_ftl_dev *dev = event_ctx;
switch (type) { switch (type) {
case SPDK_BDEV_EVENT_REMOVE: case SPDK_BDEV_EVENT_REMOVE:
assert(0); assert(0);
break; break;
case SPDK_BDEV_EVENT_MEDIA_MANAGEMENT:
assert(bdev == spdk_bdev_desc_get_bdev(dev->base_bdev_desc));
ftl_get_media_events(dev);
default: default:
break; break;
} }
@ -345,6 +350,30 @@ ftl_lba_map_request_ctor(struct spdk_mempool *mp, void *opaque, void *obj, unsig
ftl_get_num_blocks_in_band(dev), FTL_NUM_LBA_IN_BLOCK)); ftl_get_num_blocks_in_band(dev), FTL_NUM_LBA_IN_BLOCK));
} }
static int
ftl_init_media_events_pool(struct spdk_ftl_dev *dev)
{
char pool_name[128];
int rc;
rc = snprintf(pool_name, sizeof(pool_name), "ftl-media-%p", dev);
if (rc < 0 || rc >= (int)sizeof(pool_name)) {
SPDK_ERRLOG("Failed to create media pool name\n");
return -1;
}
dev->media_events_pool = spdk_mempool_create(pool_name, 1024,
sizeof(struct ftl_media_event),
SPDK_MEMPOOL_DEFAULT_CACHE_SIZE,
SPDK_ENV_SOCKET_ID_ANY);
if (!dev->media_events_pool) {
SPDK_ERRLOG("Failed to create media events pool\n");
return -1;
}
return 0;
}
static int static int
ftl_init_lba_map_pools(struct spdk_ftl_dev *dev) ftl_init_lba_map_pools(struct spdk_ftl_dev *dev)
{ {
@ -1112,6 +1141,7 @@ ftl_dev_free_sync(struct spdk_ftl_dev *dev)
spdk_mempool_free(dev->lba_pool); spdk_mempool_free(dev->lba_pool);
spdk_mempool_free(dev->nv_cache.md_pool); spdk_mempool_free(dev->nv_cache.md_pool);
spdk_mempool_free(dev->media_events_pool);
if (dev->lba_request_pool) { if (dev->lba_request_pool) {
spdk_mempool_obj_iter(dev->lba_request_pool, ftl_lba_map_request_dtor, NULL); spdk_mempool_obj_iter(dev->lba_request_pool, ftl_lba_map_request_dtor, NULL);
} }
@ -1190,6 +1220,11 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
goto fail_sync; goto fail_sync;
} }
if (ftl_init_media_events_pool(dev)) {
SPDK_ERRLOG("Unable to init media events pools\n");
goto fail_sync;
}
ftl_init_wptr_list(dev); ftl_init_wptr_list(dev);
if (ftl_dev_init_bands(dev)) { if (ftl_dev_init_bands(dev)) {