Commit 3735f2d0 authored by Tomasz Zawadzki's avatar Tomasz Zawadzki Committed by Daniel Verkamp
Browse files

blobstore: verify options passed to spdk_bs_init



Three checks are added to options passed to spdk_bs_init,
with appropriate errors returned:
- whether any of the options is set to 0
- device size has to be bigger than cluster size
- pages reserved for metadata exceed total number of clusters

Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Idee3c194b653e737ec7c7a768f1973ff72452c5b
Reviewed-on: https://review.gerrithub.io/379676


Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 9a58c40e
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -1367,11 +1367,31 @@ spdk_bs_opts_init(struct spdk_bs_opts *opts)
	opts->max_channel_ops = SPDK_BLOB_OPTS_MAX_CHANNEL_OPS;
}

static int
_spdk_bs_opts_verify(struct spdk_bs_opts *opts)
{
	if (opts->cluster_sz == 0 || opts->num_md_pages == 0 || opts->max_md_ops == 0 ||
	    opts->max_channel_ops == 0) {
		SPDK_ERRLOG("Blobstore options cannot be set to 0\n");
		return -1;
	}

	return 0;
}

static struct spdk_blob_store *
_spdk_bs_alloc(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts)
{
	struct spdk_blob_store	*bs;
	uint64_t dev_size;

	dev_size = dev->blocklen * dev->blockcnt;
	if (dev_size < opts->cluster_sz) {
		/* Device size cannot be smaller than cluster size of blobstore */
		SPDK_ERRLOG("Device size %" PRIu64 " is smaller than cluster size %d\n", dev_size,
			    opts->cluster_sz);
		return NULL;
	}
	bs = calloc(1, sizeof(struct spdk_blob_store));
	if (!bs) {
		return NULL;
@@ -1698,6 +1718,7 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
	struct spdk_bs_cpl	cpl;
	spdk_bs_sequence_t	*seq;
	uint64_t		num_md_pages;
	uint64_t		num_md_clusters;
	uint32_t		i;
	struct spdk_bs_opts	opts = {};
	int			rc;
@@ -1718,6 +1739,12 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
		spdk_bs_opts_init(&opts);
	}

	if (_spdk_bs_opts_verify(&opts) != 0) {
		dev->destroy(dev);
		cb_fn(cb_arg, NULL, -EINVAL);
		return;
	}

	bs = _spdk_bs_alloc(dev, &opts);
	if (!bs) {
		dev->destroy(dev);
@@ -1725,7 +1752,7 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
		return;
	}

	if (opts.num_md_pages == UINT32_MAX) {
	if (opts.num_md_pages == SPDK_BLOB_OPTS_NUM_MD_PAGES) {
		/* By default, allocate 1 page per cluster.
		 * Technically, this over-allocates metadata
		 * because more metadata will reduce the number
@@ -1799,8 +1826,20 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
	num_md_pages += bs->md_len;

	ctx->super->crc = _spdk_blob_md_page_calc_crc(ctx->super);

	num_md_clusters = divide_round_up(num_md_pages, bs->pages_per_cluster);
	if (num_md_clusters > bs->total_clusters) {
		SPDK_ERRLOG("Blobstore metadata cannot use more clusters than is available, "
			    "please decrease number of pages reserved for metadata "
			    "or increase cluster size.\n");
		spdk_dma_free(ctx->super);
		free(ctx);
		_spdk_bs_free(bs);
		cb_fn(cb_arg, NULL, -ENOMEM);
		return;
	}
	/* Claim all of the clusters used by the metadata */
	for (i = 0; i < divide_round_up(num_md_pages, bs->pages_per_cluster); i++) {
	for (i = 0; i < num_md_clusters; i++) {
		_spdk_bs_claim_cluster(bs, i);
	}

+24 −0
Original line number Diff line number Diff line
@@ -962,6 +962,30 @@ bs_cluster_sz(void)
	struct spdk_bs_opts opts;
	uint32_t cluster_sz;

	/* Set cluster size to zero */
	dev = init_dev();
	spdk_bs_opts_init(&opts);
	opts.cluster_sz = 0;

	/* Initialize a new blob store */
	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == -EINVAL);
	SPDK_CU_ASSERT_FATAL(g_bs == NULL);

	/*
	 * Set cluster size to blobstore page size,
	 * to work it is required to be at least twice the blobstore page size.
	 */
	dev = init_dev();
	spdk_bs_opts_init(&opts);
	opts.cluster_sz = SPDK_BS_PAGE_SIZE;

	/* Initialize a new blob store */
	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == -ENOMEM);
	SPDK_CU_ASSERT_FATAL(g_bs == NULL);

	/* Set cluster size to twice the default */
	dev = init_dev();
	spdk_bs_opts_init(&opts);
	opts.cluster_sz *= 2;