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
132 changes: 75 additions & 57 deletions src/client/api/container.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2015-2024 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -65,18 +66,18 @@ cont_inherit_redunc_fac(daos_handle_t poh, daos_prop_t *cont_prop,
return rc;
}

/**
* Real latest & greatest implementation of container create.
* Used by anyone including the daos_cont.h header file.
*/
int
daos_cont_create(daos_handle_t poh, uuid_t *cuuid, daos_prop_t *cont_prop,
daos_event_t *ev)
static int
dcsc_prop_free(tse_task_t *task, void *data);

static int
cont_create(daos_handle_t poh, const char *label, daos_prop_t *cont_prop, uuid_t *uuid,
daos_event_t *ev)
{
daos_cont_create_t *args;
tse_task_t *task;
int rc;
daos_prop_t *merged_props = NULL;
daos_prop_t *owned_prop = NULL;
daos_prop_t *prop;
int rc;

DAOS_API_ARG_ASSERT(*args, CONT_CREATE);

Expand All @@ -85,32 +86,82 @@ daos_cont_create(daos_handle_t poh, uuid_t *cuuid, daos_prop_t *cont_prop,
return -DER_INVAL;
}

if (cont_prop) {
rc = cont_inherit_redunc_fac(poh, cont_prop, &merged_props);
if (rc)
return rc;
if (label != NULL) {
owned_prop = daos_prop_alloc(1);
if (owned_prop == NULL) {
D_ERROR("failed to allocate label prop\n");
return -DER_NOMEM;
}
owned_prop->dpp_entries[0].dpe_type = DAOS_PROP_CO_LABEL;
rc = daos_prop_entry_set_str(&owned_prop->dpp_entries[0], label,
DAOS_PROP_LABEL_MAX_LEN);
if (rc != 0)
goto out;

if (cont_prop != NULL) {
daos_prop_t *tmp;

tmp = daos_prop_merge(cont_prop, owned_prop);
if (tmp == NULL) {
D_ERROR("failed to merge cont_prop and label prop\n");
rc = -DER_NOMEM;
goto out;
}
daos_prop_free(owned_prop);
owned_prop = tmp;
}
}

rc = dc_task_create(dc_cont_create, NULL, ev, &task);
if (rc) {
if (merged_props)
daos_prop_free(merged_props);
return rc;
prop = owned_prop != NULL ? owned_prop : cont_prop;

if (prop != NULL) {
daos_prop_t *tmp = NULL;

rc = cont_inherit_redunc_fac(poh, prop, &tmp);
if (rc != 0)
goto out;
if (tmp != NULL) {
daos_prop_free(owned_prop);
owned_prop = tmp;
prop = tmp;
}
}

rc = dc_task_create(dc_cont_create, NULL, ev, &task);
if (rc != 0)
goto out;

args = dc_task_get_args(task);
args->poh = poh;
uuid_clear(args->uuid);
args->prop = merged_props ? merged_props : cont_prop;
args->cuuid = cuuid;
args->prop = prop;
args->cuuid = uuid;

if (owned_prop != NULL) {
rc = dc_task_reg_comp_cb(task, dcsc_prop_free, &owned_prop, sizeof(owned_prop));
if (rc != 0) {
tse_task_complete(task, rc);
goto out;
}
}

rc = dc_task_schedule(task, true);
if (merged_props)
daos_prop_free(merged_props);
return dc_task_schedule(task, true);

out:
daos_prop_free(owned_prop);
return rc;
}

/*
* Real latest & greatest implementation of container create.
* Used by anyone including the daos_cont.h header file.
*/
int
daos_cont_create(daos_handle_t poh, uuid_t *cuuid, daos_prop_t *cont_prop, daos_event_t *ev)
{
return cont_create(poh, NULL /* label */, cont_prop, cuuid, ev);
}

#undef daos_cont_create
int
daos_cont_create(daos_handle_t poh, uuid_t *cuuid, daos_prop_t *cont_prop,
Expand All @@ -122,40 +173,7 @@ daos_cont_create_with_label(daos_handle_t poh, const char *label,
daos_prop_t *cont_prop, uuid_t *uuid,
daos_event_t *ev)
{
daos_prop_t *label_prop;
daos_prop_t *merged_props = NULL;
int rc;

label_prop = daos_prop_alloc(1);
if (label_prop == NULL) {
D_ERROR("failed to allocate label_prop\n");
return -DER_NOMEM;
}
label_prop->dpp_entries[0].dpe_type = DAOS_PROP_CO_LABEL;
rc = daos_prop_entry_set_str(&label_prop->dpp_entries[0], label, DAOS_PROP_LABEL_MAX_LEN);
if (rc)
goto out_prop;

if (cont_prop) {
merged_props = daos_prop_merge(cont_prop, label_prop);
if (merged_props == NULL) {
D_ERROR("failed to merge cont_prop and label_prop\n");
rc = -DER_NOMEM;
goto out_prop;
}
}

rc = daos_cont_create(poh, uuid, merged_props ? merged_props : label_prop, ev);
if (rc != 0) {
D_ERROR("daos_cont_create label=%s failed, "DF_RC"\n", label, DP_RC(rc));
goto out_merged_props;
}

out_merged_props:
daos_prop_free(merged_props);
out_prop:
daos_prop_free(label_prop);
return rc;
return cont_create(poh, label, cont_prop, uuid, ev);
}

/**
Expand Down
104 changes: 104 additions & 0 deletions src/tests/suite/daos_container.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,106 @@ co_op_retry(void **state)
test_set_engine_fail_loc(arg, CRT_NO_RANK, 0);
}

static void
co_create_label_async_retry(void **state)
{
test_arg_t *arg = *state;
const char *label = "co_create_label_async_retry_cont";
daos_handle_t eqh;
daos_event_t ev;
daos_event_t *evp = NULL;
uuid_t uuid;
int rc;

FAULT_INJECTION_REQUIRED();

if (arg->myrank != 0)
return;

rc = daos_eq_create(&eqh);
assert_rc_equal(rc, 0);
rc = daos_event_init(&ev, eqh, NULL);
assert_rc_equal(rc, 0);

/* Force a "lost" reply so the create RPC is retried (task re-run). */
test_set_engine_fail_loc(arg, CRT_NO_RANK, DAOS_MD_OP_PASS_NOREPLY | DAOS_FAIL_ONCE);
print_message("creating container %s asynchronously (retry / use-after-free) ... ", label);
rc = daos_cont_create_with_label(arg->pool.poh, label, NULL, &uuid, &ev);
assert_rc_equal(rc, 0);

rc = daos_eq_poll(eqh, 1, DAOS_EQ_WAIT, 1, &evp);
assert_rc_equal(rc, 1);
assert_ptr_equal(evp, &ev);
assert_int_equal(ev.ev_error, 0);
print_message("success, created container: " DF_UUID "\n", DP_UUID(uuid));
test_set_engine_fail_loc(arg, CRT_NO_RANK, 0);

rc = daos_event_fini(&ev);
assert_rc_equal(rc, 0);
rc = daos_eq_destroy(eqh, 0);
assert_rc_equal(rc, 0);

print_message("destroying container %s ... ", label);
rc = daos_cont_destroy(arg->pool.poh, label, 1 /* force */, NULL);
assert_rc_equal(rc, 0);
print_message("success\n");
}

static void
co_create_label_rf_async_retry(void **state)
{
test_arg_t *arg = *state;
const char *label = "co_create_label_props_async_retry_cont";
daos_prop_t *prop;
daos_handle_t eqh;
daos_event_t ev;
daos_event_t *evp = NULL;
uuid_t uuid;
int rc;

FAULT_INJECTION_REQUIRED();

if (arg->myrank != 0)
return;

prop = daos_prop_alloc(1);
assert_non_null(prop);
prop->dpp_entries[0].dpe_type = DAOS_PROP_CO_REDUN_FAC;
prop->dpp_entries[0].dpe_val = DAOS_PROP_CO_REDUN_RF0;

rc = daos_eq_create(&eqh);
assert_rc_equal(rc, 0);
rc = daos_event_init(&ev, eqh, NULL);
assert_rc_equal(rc, 0);

/* Force a "lost" reply so the create RPC is retried (task re-run). */
test_set_engine_fail_loc(arg, CRT_NO_RANK, DAOS_MD_OP_PASS_NOREPLY | DAOS_FAIL_ONCE);
print_message("creating container %s with props asynchronously (retry / use-after-free) "
"... ",
label);
rc = daos_cont_create_with_label(arg->pool.poh, label, prop, &uuid, &ev);
assert_rc_equal(rc, 0);

rc = daos_eq_poll(eqh, 1, DAOS_EQ_WAIT, 1, &evp);
assert_rc_equal(rc, 1);
assert_ptr_equal(evp, &ev);
assert_int_equal(ev.ev_error, 0);
print_message("success, created container: " DF_UUID "\n", DP_UUID(uuid));
test_set_engine_fail_loc(arg, CRT_NO_RANK, 0);

rc = daos_event_fini(&ev);
assert_rc_equal(rc, 0);
rc = daos_eq_destroy(eqh, 0);
assert_rc_equal(rc, 0);

daos_prop_free(prop);

print_message("destroying container %s ... ", label);
rc = daos_cont_destroy(arg->pool.poh, label, 1 /* force */, NULL);
assert_rc_equal(rc, 0);
print_message("success\n");
}

static void
co_acl_get(test_arg_t *arg, struct daos_acl *exp_acl,
const char *exp_owner, const char *exp_owner_grp)
Expand Down Expand Up @@ -4163,6 +4263,10 @@ static const struct CMUnitTest co_tests[] = {
{"CONT34: evict handles", co_evict_hdls, NULL, test_case_teardown},
{"CONT35: container duplicate op detection timing", co_op_dup_timing, NULL, test_case_teardown},
{"CONT36: open DESTROYING", co_open_destroying, NULL, test_case_teardown},
{"CONT37: retry async cont create with label", co_create_label_async_retry, NULL,
test_case_teardown},
{"CONT38: retry async cont create with label and RF", co_create_label_rf_async_retry, NULL,
test_case_teardown},
};

int
Expand Down
Loading