diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fb6fbf2..ee45419f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,18 @@ ### bdev -An `opts_size`element was added in the `spdk_bdev_opts` structure to solve the +An `opts_size` element was added in the `spdk_bdev_opts` structure to solve the ABI compatiblity issue between different SPDK version. And also add `opts_size` parameter in spdk_bdev_get_opts function. Two fields `small_buf_pool_size` and `large_buf_pool_size` were added into spdk_bdev_opts, which were used to determine the small and large buffer pool size of the whole bdev module. +### blob + +An `opts_size` element was added in the `spdk_bs_opts` structure to solve the +ABI compatiblity issue between different SPDK version. And also add `opts_size` +parameter in `spdk_bs_opts_init` function. + ### event The pci_whitelist and pci_blacklist members of struct spdk_app_opts have been diff --git a/include/spdk/blob.h b/include/spdk/blob.h index 7bcac9ba5..0674d011b 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -225,14 +225,23 @@ struct spdk_bs_opts { /** Argument passed to iter_cb_fn for each blob. */ void *iter_cb_arg; + + /** + * The size of spdk_bs_opts according to the caller of this library is used for ABI + * compatibility. The library uses this field to know how many fields in this + * structure are valid. And the library will populate any remaining fields with default values. + * After that, new added fields should be put in the end of the struct. + */ + size_t opts_size; }; /** * Initialize a spdk_bs_opts structure to the default blobstore option values. * * \param opts The spdk_bs_opts structure to be initialized. + * \param opts_size The opts_size must be the size of spdk_bs_opts structure. */ -void spdk_bs_opts_init(struct spdk_bs_opts *opts); +void spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size); /** * Load a blobstore from the given device. diff --git a/lib/blob/Makefile b/lib/blob/Makefile index 53ae6800b..b02fad5cf 100644 --- a/lib/blob/Makefile +++ b/lib/blob/Makefile @@ -34,7 +34,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -SO_VER := 3 +SO_VER := 4 SO_MINOR := 0 C_SRCS = blobstore.c request.c zeroes.c blob_bs_dev.c diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index c21efc985..164bb6814 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -3131,16 +3131,45 @@ bs_free(struct spdk_blob_store *bs) } void -spdk_bs_opts_init(struct spdk_bs_opts *opts) +spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size) { - opts->cluster_sz = SPDK_BLOB_OPTS_CLUSTER_SZ; - opts->num_md_pages = SPDK_BLOB_OPTS_NUM_MD_PAGES; - opts->max_md_ops = SPDK_BLOB_OPTS_MAX_MD_OPS; - opts->max_channel_ops = SPDK_BLOB_OPTS_DEFAULT_CHANNEL_OPS; - opts->clear_method = BS_CLEAR_WITH_UNMAP; - memset(&opts->bstype, 0, sizeof(opts->bstype)); - opts->iter_cb_fn = NULL; - opts->iter_cb_arg = NULL; + + if (!opts) { + SPDK_ERRLOG("opts should not be NULL\n"); + return; + } + + if (!opts_size) { + SPDK_ERRLOG("opts_size should not be zero value\n"); + return; + } + + memset(opts, 0, opts_size); + opts->opts_size = opts_size; + +#define FIELD_OK(field) \ + offsetof(struct spdk_bs_opts, field) + sizeof(opts->field) <= opts_size + +#define SET_FIELD(field, value) \ + if (FIELD_OK(field)) { \ + opts->field = value; \ + } \ + + SET_FIELD(cluster_sz, SPDK_BLOB_OPTS_CLUSTER_SZ); + SET_FIELD(num_md_pages, SPDK_BLOB_OPTS_NUM_MD_PAGES); + SET_FIELD(max_md_ops, SPDK_BLOB_OPTS_NUM_MD_PAGES); + SET_FIELD(max_channel_ops, SPDK_BLOB_OPTS_DEFAULT_CHANNEL_OPS); + SET_FIELD(clear_method, BS_CLEAR_WITH_UNMAP); + + if (FIELD_OK(bstype)) { + memset(&opts->bstype, 0, sizeof(opts->bstype)); + } + + SET_FIELD(iter_cb_fn, NULL); + SET_FIELD(iter_cb_arg, NULL); + +#undef FIELD_OK +#undef SET_FIELD } static int @@ -4271,6 +4300,47 @@ bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) } } +static int +bs_opts_copy(struct spdk_bs_opts *src, struct spdk_bs_opts *dst) +{ + + if (!src->opts_size) { + SPDK_ERRLOG("opts_size should not be zero value\n"); + return -1; + } + +#define FIELD_OK(field) \ + offsetof(struct spdk_bs_opts, field) + sizeof(src->field) <= src->opts_size + +#define SET_FIELD(field) \ + if (FIELD_OK(field)) { \ + dst->field = src->field; \ + } \ + + SET_FIELD(cluster_sz); + SET_FIELD(num_md_pages); + SET_FIELD(max_md_ops); + SET_FIELD(max_channel_ops); + SET_FIELD(clear_method); + + if (FIELD_OK(bstype)) { + memcpy(&dst->bstype, &src->bstype, sizeof(dst->bstype)); + } + SET_FIELD(iter_cb_fn); + SET_FIELD(iter_cb_arg); + + dst->opts_size = src->opts_size; + + /* You should not remove this statement, but need to update the assert statement + * if you add a new field, and also add a corresponding SET_FIELD statement */ + SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_opts) == 64, "Incorrect size"); + +#undef FIELD_OK +#undef SET_FIELD + + return 0; +} + void spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, spdk_bs_op_with_handle_complete cb_fn, void *cb_arg) @@ -4290,10 +4360,11 @@ spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, return; } + spdk_bs_opts_init(&opts, sizeof(opts)); if (o) { - opts = *o; - } else { - spdk_bs_opts_init(&opts); + if (bs_opts_copy(o, &opts)) { + return; + } } if (opts.max_md_ops == 0 || opts.max_channel_ops == 0) { @@ -4549,7 +4620,7 @@ spdk_bs_dump(struct spdk_bs_dev *dev, FILE *fp, spdk_bs_dump_print_xattr print_x SPDK_DEBUGLOG(blob, "Dumping blobstore from dev %p\n", dev); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); err = bs_alloc(dev, &opts, &bs, &ctx); if (err) { @@ -4634,10 +4705,11 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, return; } + spdk_bs_opts_init(&opts, sizeof(opts)); if (o) { - opts = *o; - } else { - spdk_bs_opts_init(&opts); + if (bs_opts_copy(o, &opts)) { + return; + } } if (bs_opts_verify(&opts) != 0) { diff --git a/lib/blobfs/blobfs.c b/lib/blobfs/blobfs.c index d01aaec45..c9bcde899 100644 --- a/lib/blobfs/blobfs.c +++ b/lib/blobfs/blobfs.c @@ -623,7 +623,7 @@ spdk_fs_init(struct spdk_bs_dev *dev, struct spdk_blobfs_opts *opt, args->arg = cb_arg; args->fs = fs; - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), SPDK_BLOBFS_SIGNATURE); if (opt) { opts.cluster_sz = opt->cluster_sz; @@ -865,7 +865,7 @@ spdk_fs_load(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, args->arg = cb_arg; args->fs = fs; TAILQ_INIT(&args->op.fs_load.deleted_files); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); bs_opts.iter_cb_fn = iter_cb; bs_opts.iter_cb_arg = req; spdk_bs_load(dev, &bs_opts, load_cb, req); diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index daef811b3..d60945f3c 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -385,7 +385,7 @@ lvs_load_cb(void *cb_arg, struct spdk_blob_store *bs, int lvolerrno) static void lvs_bs_opts_init(struct spdk_bs_opts *opts) { - spdk_bs_opts_init(opts); + spdk_bs_opts_init(opts, sizeof(*opts)); opts->max_channel_ops = SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS; } diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 929e853fe..8d5739f01 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -607,7 +607,7 @@ blob_thin_provision(void) spdk_blob_id blobid; dev = init_dev(); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); /* Initialize a new blob store */ @@ -1166,7 +1166,7 @@ blob_read_only(void) int rc; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); @@ -2161,7 +2161,7 @@ bs_load(void) struct spdk_blob_opts blob_opts; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); /* Initialize a new blob store */ @@ -2227,7 +2227,7 @@ bs_load(void) /* Load should when max_md_ops is set to zero */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.max_md_ops = 0; spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2235,7 +2235,7 @@ bs_load(void) /* Load should when max_channel_ops is set to zero */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.max_channel_ops = 0; spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2243,7 +2243,7 @@ bs_load(void) /* Load an existing blob store */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2293,7 +2293,7 @@ bs_load(void) dev = init_dev(); dev->blockcnt /= 2; - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2304,7 +2304,7 @@ bs_load(void) dev = init_dev(); dev->blockcnt *= 4; - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2323,7 +2323,7 @@ bs_load(void) super_block->size = 0; super_block->crc = blob_md_page_calc_crc(super_block); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2457,7 +2457,7 @@ bs_load_custom_cluster_size(void) uint64_t total_clusters; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = custom_cluster_size; snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); @@ -2483,7 +2483,7 @@ bs_load_custom_cluster_size(void) /* Load an existing blob store */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -2513,7 +2513,7 @@ bs_type(void) struct spdk_bs_opts opts; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); /* Initialize a new blob store */ @@ -2598,7 +2598,7 @@ bs_super_block(void) struct spdk_bs_super_block_ver1 super_block_v1; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); /* Initialize a new blob store */ @@ -2697,7 +2697,7 @@ bs_cluster_sz(void) /* Set cluster size to zero */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = 0; /* Initialize a new blob store */ @@ -2711,7 +2711,7 @@ bs_cluster_sz(void) * to work it is required to be at least twice the blobstore page size. */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = SPDK_BS_PAGE_SIZE; /* Initialize a new blob store */ @@ -2725,7 +2725,7 @@ bs_cluster_sz(void) * to work it is required to be at least twice the blobstore page size. */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = SPDK_BS_PAGE_SIZE - 1; /* Initialize a new blob store */ @@ -2736,7 +2736,7 @@ bs_cluster_sz(void) /* Set cluster size to twice the default */ dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz *= 2; cluster_sz = opts.cluster_sz; @@ -2824,7 +2824,7 @@ bs_resize_md(void) dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; cluster_sz = opts.cluster_sz; @@ -2921,7 +2921,7 @@ blob_serialize_test(void) dev = init_dev(); /* Initialize a new blobstore with very small clusters */ - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); opts.cluster_sz = dev->blocklen * 8; spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); poll_threads(); @@ -4069,7 +4069,7 @@ bs_load_iter_test(void) struct spdk_bs_opts opts; dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); /* Initialize a new blob store */ @@ -4103,7 +4103,7 @@ bs_load_iter_test(void) CU_ASSERT(g_bserrno == 0); dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); opts.iter_cb_fn = test_iter; opts.iter_cb_arg = &iter_ctx; @@ -4119,7 +4119,7 @@ bs_load_iter_test(void) bs_free(bs); dev = init_dev(); - spdk_bs_opts_init(&opts); + spdk_bs_opts_init(&opts, sizeof(opts)); snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); opts.iter_cb_fn = test_iter; iter_ctx.current_iter = 0; @@ -4673,7 +4673,7 @@ blob_relations(void) spdk_blob_id ids[10] = {}; dev = init_dev(); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); @@ -4999,7 +4999,7 @@ blob_relations2(void) spdk_blob_id ids[10] = {}; dev = init_dev(); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); @@ -6194,7 +6194,7 @@ blob_io_unit(void) /* Create dev with 512 bytes io unit size */ - spdk_bs_opts_init(&bsopts); + spdk_bs_opts_init(&bsopts, sizeof(bsopts)); bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */ snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE"); @@ -6331,7 +6331,7 @@ blob_io_unit_compatiblity(void) /* Create dev with 512 bytes io unit size */ - spdk_bs_opts_init(&bsopts); + spdk_bs_opts_init(&bsopts, sizeof(bsopts)); bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */ snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE"); diff --git a/test/unit/lib/lvol/lvol.c/lvol_ut.c b/test/unit/lib/lvol/lvol.c/lvol_ut.c index 72f7b6e81..f779b985c 100644 --- a/test/unit/lib/lvol/lvol.c/lvol_ut.c +++ b/test/unit/lib/lvol/lvol.c/lvol_ut.c @@ -332,8 +332,9 @@ spdk_blob_get_id(struct spdk_blob *blob) } void -spdk_bs_opts_init(struct spdk_bs_opts *opts) +spdk_bs_opts_init(struct spdk_bs_opts *opts, size_t opts_size) { + opts->opts_size = opts_size; opts->cluster_sz = SPDK_BLOB_OPTS_CLUSTER_SZ; opts->num_md_pages = SPDK_BLOB_OPTS_NUM_MD_PAGES; opts->max_md_ops = SPDK_BLOB_OPTS_MAX_MD_OPS; @@ -1053,7 +1054,7 @@ lvs_load(void) SPDK_CU_ASSERT_FATAL(req != NULL); init_dev(&dev); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE"); spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL); SPDK_CU_ASSERT_FATAL(dev.bs != NULL); @@ -1143,7 +1144,7 @@ lvols_load(void) SPDK_CU_ASSERT_FATAL(req != NULL); init_dev(&dev); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE"); spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL); super_blob = calloc(1, sizeof(*super_blob)); @@ -1250,7 +1251,7 @@ lvol_open(void) SPDK_CU_ASSERT_FATAL(req != NULL); init_dev(&dev); - spdk_bs_opts_init(&bs_opts); + spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "LVOLSTORE"); spdk_bs_init(&dev.bs_dev, &bs_opts, null_cb, NULL); super_blob = calloc(1, sizeof(*super_blob));