diff --git a/include/spdk/ftl.h b/include/spdk/ftl.h index a2ac2952e..80d37145b 100644 --- a/include/spdk/ftl.h +++ b/include/spdk/ftl.h @@ -64,6 +64,18 @@ struct spdk_ftl_attrs { typedef void (*spdk_ftl_fn)(void *cb_arg, int status); typedef void (*spdk_ftl_init_fn)(struct spdk_ftl_dev *dev, void *cb_arg, int status); +/** + * Initializes the FTL library. + * + * @return 0 on success, negative errno otherwise. + */ +int spdk_ftl_init(void); + +/** + * Deinitializes the FTL library. + */ +void spdk_ftl_fini(void); + /** * Initialize the FTL on the given pair of bdevs - base and cache bdev. * Upon receiving a successful completion callback user is free to use I/O calls. diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 89cd29d34..9e9459ca6 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -136,6 +136,35 @@ ftl_core_poller(void *ctx) return SPDK_POLLER_IDLE; } +void *g_ftl_write_buf; +void *g_ftl_read_buf; + +int +spdk_ftl_init(void) +{ + g_ftl_write_buf = spdk_zmalloc(FTL_ZERO_BUFFER_SIZE, FTL_ZERO_BUFFER_SIZE, NULL, + SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (!g_ftl_write_buf) { + return -ENOMEM; + } + + g_ftl_read_buf = spdk_zmalloc(FTL_ZERO_BUFFER_SIZE, FTL_ZERO_BUFFER_SIZE, NULL, + SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (!g_ftl_read_buf) { + spdk_free(g_ftl_write_buf); + g_ftl_write_buf = NULL; + return -ENOMEM; + } + return 0; +} + +void +spdk_ftl_fini(void) +{ + spdk_free(g_ftl_write_buf); + spdk_free(g_ftl_read_buf); +} + struct spdk_io_channel * spdk_ftl_get_io_channel(struct spdk_ftl_dev *dev) { diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index 4374f27e8..c95cc9642 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -21,6 +21,13 @@ #include "ftl_layout.h" #include "utils/ftl_log.h" +/* When using VSS on nvcache, FTL sometimes doesn't require the contents of metadata. + * Some devices have bugs when sending a NULL pointer as part of metadata when namespace + * is formatted with VSS. This buffer is passed to such calls to avoid the bug. */ +#define FTL_ZERO_BUFFER_SIZE 0x100000 +extern void *g_ftl_write_buf; +extern void *g_ftl_read_buf; + struct spdk_ftl_dev { /* Configuration */ struct spdk_ftl_conf conf; diff --git a/lib/ftl/ftl_nv_cache_io.h b/lib/ftl/ftl_nv_cache_io.h index 82e9471fb..f07e44b09 100644 --- a/lib/ftl/ftl_nv_cache_io.h +++ b/lib/ftl/ftl_nv_cache_io.h @@ -43,7 +43,7 @@ ftl_nv_cache_bdev_read_blocks_with_md(struct spdk_ftl_dev *dev, uint64_t offset_blocks, uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg) { - return spdk_bdev_read_blocks_with_md(desc, ch, buf, md, + return spdk_bdev_read_blocks_with_md(desc, ch, buf, md ? : g_ftl_read_buf, offset_blocks, num_blocks, cb, cb_arg); } @@ -56,7 +56,7 @@ ftl_nv_cache_bdev_write_blocks_with_md(struct spdk_ftl_dev *dev, uint64_t offset_blocks, uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg) { - return spdk_bdev_write_blocks_with_md(desc, ch, buf, md, + return spdk_bdev_write_blocks_with_md(desc, ch, buf, md ? : g_ftl_write_buf, offset_blocks, num_blocks, cb, cb_arg); } diff --git a/lib/ftl/mngt/ftl_mngt_bdev.c b/lib/ftl/mngt/ftl_mngt_bdev.c index e07dc6839..5f0aff24f 100644 --- a/lib/ftl/mngt/ftl_mngt_bdev.c +++ b/lib/ftl/mngt/ftl_mngt_bdev.c @@ -228,6 +228,12 @@ ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt goto error; } + if (ftl_md_xfer_blocks(dev) * dev->cache_md_size > FTL_ZERO_BUFFER_SIZE) { + FTL_ERRLOG(dev, "Zero buffer too small for bdev %s metadata transfer\n", + spdk_bdev_get_name(bdev)); + goto error; + } + ftl_mngt_next_step(mngt); return; error: diff --git a/lib/ftl/spdk_ftl.map b/lib/ftl/spdk_ftl.map index e3ba837e5..1ff8c97ed 100644 --- a/lib/ftl/spdk_ftl.map +++ b/lib/ftl/spdk_ftl.map @@ -2,6 +2,8 @@ global: # public functions + spdk_ftl_init; + spdk_ftl_fini; spdk_ftl_dev_init; spdk_ftl_dev_free; spdk_ftl_get_default_conf; diff --git a/module/bdev/ftl/bdev_ftl.c b/module/bdev/ftl/bdev_ftl.c index 837e101f1..a1a48ea1a 100644 --- a/module/bdev/ftl/bdev_ftl.c +++ b/module/bdev/ftl/bdev_ftl.c @@ -36,6 +36,7 @@ struct ftl_deferred_init { static LIST_HEAD(, ftl_deferred_init) g_deferred_init = LIST_HEAD_INITIALIZER(g_deferred_init); static int bdev_ftl_initialize(void); +static void bdev_ftl_finish(void); static void bdev_ftl_examine(struct spdk_bdev *bdev); static int @@ -47,6 +48,7 @@ bdev_ftl_get_ctx_size(void) static struct spdk_bdev_module g_ftl_if = { .name = "ftl", .module_init = bdev_ftl_initialize, + .module_fini = bdev_ftl_finish, .examine_disk = bdev_ftl_examine, .get_ctx_size = bdev_ftl_get_ctx_size, }; @@ -370,7 +372,7 @@ error: static int bdev_ftl_initialize(void) { - return 0; + return spdk_ftl_init(); } void @@ -384,6 +386,12 @@ bdev_ftl_delete_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_a } } +static void +bdev_ftl_finish(void) +{ + spdk_ftl_fini(); +} + static void bdev_ftl_create_defered_cb(const struct ftl_bdev_info *info, void *ctx, int status) {