Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 59 additions & 13 deletions src/control/lib/spdk/ctests/nvme_control_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
#include "nvme_internal.h"

#include "../include/nvme_control_common.h"
#include "../include/nvme_control.h"

#if D_HAS_WARNING(4, "-Wframe-larger-than=")
#pragma GCC diagnostic ignored "-Wframe-larger-than="
#endif

#define MAX_MOCK_PCI_DEVS 16

static struct ret_t *test_ret;
static int mock_pci_dev_count;

/**
* ==============================
Expand Down Expand Up @@ -85,15 +89,18 @@ mock_copy_ctrlr_data(struct nvme_ctrlr_t *ctrlr, const struct spdk_nvme_ctrlr_da
return 0;
}

/*
* Return a unique device per call from a static local pool (indexed by
* mock_pci_dev_count, reset in teardown).
*/
static struct spdk_pci_device *
mock_spdk_nvme_ctrlr_get_pci_device(struct spdk_nvme_ctrlr *ctrlr)
{
struct spdk_pci_device *dev;

dev = calloc(1, sizeof(struct spdk_pci_device));
static struct spdk_pci_device devs[MAX_MOCK_PCI_DEVS];

(void)ctrlr;
return dev;
assert_true(mock_pci_dev_count < MAX_MOCK_PCI_DEVS);
return &devs[mock_pci_dev_count++];
}

static int
Expand Down Expand Up @@ -274,6 +281,46 @@ test_get_controller(void **state)
assert_return_code(rc, 0);
}

/*
* This test should be run with ASan to detect the memory leak fixed by DAOS-19019. It verifies
* that the opts.pci_allowed buffer built by opts_add_pci_addr() is freed before daos_spdk_init()
* returns.
*/
static void
test_daos_spdk_init_pci_freed(void **state)
{
char *pcil[] = {"0000:01:00.0"};

(void)state;

test_ret = daos_spdk_init(0, NULL, 1, pcil);
/* spdk_env_init() is expected to fail in a unit-test context (no hugepages) */
assert_non_null(test_ret);
}

/*
* This test should be run with ASan to detect the memory leak fixed by DAOS-19019. It verifies
* that pci_addr is freed by teardown via clean_ret() -> free_ctrlr_fields().
*/
static void
test_collect_pci_addr_freed(void **state)
{
(void)state;

/*
* Inject two mock controllers and drive _collect() via function pointers instead of real
* SPDK calls.
*/
attach_mock_controllers();
test_ret = init_ret();
_collect(test_ret, &mock_copy_ctrlr_data, &mock_spdk_nvme_ctrlr_get_pci_device,
&mock_spdk_pci_device_get_numa_id, &mock_spdk_pci_device_get_type);
assert_int_equal(test_ret->rc, 0);
assert_non_null(test_ret->ctrlrs);
assert_non_null(test_ret->ctrlrs->pci_addr);
assert_non_null(test_ret->ctrlrs->next->pci_addr);
}

static int
setup(void **state)
{
Expand All @@ -291,6 +338,7 @@ teardown(void **state)
free(test_ret);
test_ret = NULL;
cleanup(false);
mock_pci_dev_count = 0;

return 0;
}
Expand All @@ -299,15 +347,13 @@ int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(test_discover_null_controllers,
setup, teardown),
cmocka_unit_test_setup_teardown(test_discover_set_controllers,
setup, teardown),
cmocka_unit_test_setup_teardown(test_discover_probe_fail, setup,
teardown),
cmocka_unit_test_setup_teardown(test_collect, setup, teardown),
cmocka_unit_test_setup_teardown(test_get_controller, setup,
teardown),
cmocka_unit_test_setup_teardown(test_discover_null_controllers, setup, teardown),
cmocka_unit_test_setup_teardown(test_discover_set_controllers, setup, teardown),
cmocka_unit_test_setup_teardown(test_discover_probe_fail, setup, teardown),
cmocka_unit_test_setup_teardown(test_collect, setup, teardown),
cmocka_unit_test_setup_teardown(test_get_controller, setup, teardown),
cmocka_unit_test_setup_teardown(test_daos_spdk_init_pci_freed, setup, teardown),
cmocka_unit_test_setup_teardown(test_collect_pci_addr_freed, setup, teardown),
};

return cmocka_run_group_tests_name("control_nvme_control_ut", tests,
Expand Down
2 changes: 2 additions & 0 deletions src/control/lib/spdk/src/nvme_control.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2018-2022 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
* (C) Copyright 2025 Google LLC
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
Expand Down Expand Up @@ -522,6 +523,7 @@ daos_spdk_init(int mem_sz, char *env_ctx, size_t nr_pcil, char **pcil)
}

out:
free(opts.pci_allowed);
ret->rc = rc;
return ret;
}
Expand Down
2 changes: 2 additions & 0 deletions src/control/lib/spdk/src/nvme_control_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ free_ctrlr_fields(struct nvme_ctrlr_t *ctrlr)
free(ctrlr->vendor_id);
if (ctrlr->pci_type != NULL)
free(ctrlr->pci_type);
if (ctrlr->pci_addr != NULL)
free(ctrlr->pci_addr);
}

void
Expand Down
Loading