From 82b7b4aad53c5eb17a4729c41c7a51861715d519 Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Tue, 14 Jan 2020 05:15:41 -0500 Subject: [PATCH] lib/ftl: Media management events Adding support for handling media management events. Change-Id: I1b87143ddd360e314385e8dc70359aeb0d526b5a Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481691 Tested-by: SPDK CI Jenkins Community-CI: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: Konrad Sztyber --- lib/ftl/ftl_core.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ lib/ftl/ftl_core.h | 11 ++++++++ lib/ftl/ftl_init.c | 35 ++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 21b94a82f..3f2f5c37d 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -2157,6 +2157,69 @@ ftl_addr_is_written(struct ftl_band *band, struct ftl_addr addr) 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 ftl_process_retry_queue(struct spdk_ftl_dev *dev) { diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index b6bbb0f93..dce5b3f9e 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -167,6 +167,9 @@ struct spdk_ftl_dev { /* LBA map requests pool */ struct spdk_mempool *lba_request_pool; + /* Media management events pool */ + struct spdk_mempool *media_events_pool; + /* Statistics */ struct ftl_stats stats; @@ -247,6 +250,13 @@ struct ftl_nv_cache_header { uint32_t checksum; } __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); 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); int ftl_nv_cache_scrub(struct ftl_nv_cache *nv_cache, spdk_bdev_io_completion_cb cb_fn, void *cb_arg); +void ftl_get_media_events(struct spdk_ftl_dev *dev); struct spdk_io_channel * ftl_get_io_channel(const struct spdk_ftl_dev *dev); diff --git a/lib/ftl/ftl_init.c b/lib/ftl/ftl_init.c index 75870c009..80ef920ad 100644 --- a/lib/ftl/ftl_init.c +++ b/lib/ftl/ftl_init.c @@ -216,10 +216,15 @@ ftl_dev_init_bands(struct spdk_ftl_dev *dev) static void 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) { case SPDK_BDEV_EVENT_REMOVE: assert(0); break; + case SPDK_BDEV_EVENT_MEDIA_MANAGEMENT: + assert(bdev == spdk_bdev_desc_get_bdev(dev->base_bdev_desc)); + ftl_get_media_events(dev); default: 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)); } +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 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->nv_cache.md_pool); + spdk_mempool_free(dev->media_events_pool); if (dev->lba_request_pool) { 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; } + if (ftl_init_media_events_pool(dev)) { + SPDK_ERRLOG("Unable to init media events pools\n"); + goto fail_sync; + } + ftl_init_wptr_list(dev); if (ftl_dev_init_bands(dev)) {