Commit 04524ea4 authored by Jinlong Chen's avatar Jinlong Chen Committed by Ben Walker
Browse files

blob: fix possible memory leak in bs loading



If I/O errors happen during blobstore loading, the allocated memory for
spdk_bs_load_ctx->mask may be leaked.

Change-Id: I7e802dfb1b719b1ba23f70bdb216e7f9cb35357e
Signed-off-by: default avatarJinlong Chen <chenjinlong.cjl@alibaba-inc.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/25470


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Community-CI: Mellanox Build Bot
Community-CI: Community CI Samsung <spdk.community.ci.samsung@gmail.com>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
parent 61617956
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -4006,6 +4006,7 @@ bs_load_ctx_fail(struct spdk_bs_load_ctx *ctx, int bserrno)
{
	assert(bserrno != 0);

	spdk_free(ctx->mask);
	spdk_free(ctx->super);
	bs_sequence_finish(ctx->seq, bserrno);
	bs_free(ctx->bs);
@@ -4301,7 +4302,6 @@ bs_load_iter(void *arg, struct spdk_blob *blob, int bserrno)
	ctx->iter_cb_fn = NULL;

	spdk_free(ctx->super);
	spdk_free(ctx->mask);
	bs_sequence_finish(ctx->seq, bserrno);
	free(ctx);
}
@@ -4338,12 +4338,13 @@ bs_load_used_blobids_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)

	rc = spdk_bit_array_resize(&ctx->bs->used_blobids, ctx->mask->length);
	if (rc < 0) {
		spdk_free(ctx->mask);
		bs_load_ctx_fail(ctx, rc);
		return;
	}

	spdk_bit_array_load_mask(ctx->bs->used_blobids, ctx->mask->mask);
	spdk_free(ctx->mask);

	bs_load_complete(ctx);
}

@@ -4428,7 +4429,6 @@ bs_load_used_pages_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)

	rc = spdk_bit_array_resize(&ctx->bs->used_md_pages, ctx->mask->length);
	if (rc < 0) {
		spdk_free(ctx->mask);
		bs_load_ctx_fail(ctx, rc);
		return;
	}
@@ -4679,6 +4679,9 @@ bs_load_write_used_clusters_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserr
{
	struct spdk_bs_load_ctx	*ctx = cb_arg;

	spdk_free(ctx->mask);
	ctx->mask = NULL;

	if (bserrno != 0) {
		bs_load_ctx_fail(ctx, bserrno);
		return;
+47 −0
Original line number Diff line number Diff line
@@ -2829,6 +2829,52 @@ bs_load_after_failed_grow(void)
	g_bs = NULL;
}

static void
bs_load_error(void)
{
	struct spdk_blob_store *bs;
	struct spdk_bs_dev *dev;
	struct spdk_bs_opts opts;
	struct spdk_power_failure_thresholds thresholds = {};

	dev = init_dev();
	spdk_bs_opts_init(&opts, sizeof(opts));
	snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE");

	/* Initialize a new blob store */
	spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);
	SPDK_CU_ASSERT_FATAL(g_bs != NULL);
	bs = g_bs;

	/* Unload the blob store */
	spdk_bs_unload(bs, bs_op_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == 0);

	/* Load fails with I/O error */
	thresholds.general_threshold = 2;
	dev_set_power_failure_thresholds(thresholds);
	g_bserrno = -1;
	dev = init_dev();
	spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == -EIO);
	CU_ASSERT(g_bs == NULL);
	dev_reset_power_failure_event();

	/* Load fails with NOMEM error */
	g_bserrno = -1;
	dev = init_dev();
	spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL);
	MOCK_SET(spdk_zmalloc, NULL);
	poll_threads();
	CU_ASSERT(g_bserrno == -ENOMEM);
	CU_ASSERT(g_bs == NULL);
	MOCK_CLEAR(spdk_zmalloc);
}

static void
bs_type(void)
{
@@ -10143,6 +10189,7 @@ main(int argc, char **argv)
		CU_ADD_TEST(suite_bs, bs_load_pending_removal);
		CU_ADD_TEST(suite, bs_load_custom_cluster_size);
		CU_ADD_TEST(suite, bs_load_after_failed_grow);
		CU_ADD_TEST(suite, bs_load_error);
		CU_ADD_TEST(suite_bs, bs_unload);
		CU_ADD_TEST(suite, bs_cluster_sz);
		CU_ADD_TEST(suite_bs, bs_usable_clusters);