Skip to content

Commit

Permalink
DAOS-15885 vos: check DTX visibility when probe for EV iteration
Browse files Browse the repository at this point in the history
To avoid locating the iteration position (for the first time) on
some invisible EV data (with in-processing or aborted DTX).

Allow-unstable-test: true

Signed-off-by: Fan Yong <fan.yong@intel.com>
  • Loading branch information
Nasf-Fan committed May 26, 2024
1 parent 3a1d29c commit 14d43dc
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 31 deletions.
104 changes: 104 additions & 0 deletions src/tests/suite/daos_base_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,108 @@ dtx_21(void **state)
ioreq_fini(&req);
}

static void
dtx_22(void **state)
{
test_arg_t *arg = *state;
daos_obj_id_t oid;
daos_handle_t oh;
daos_iod_t iod = { 0 };
d_sg_list_t sgl = { 0 };
daos_recx_t recx[2];
d_iov_t val_iov[2];
d_iov_t dkey;
d_iov_t akey;
uint64_t dkey_val = 100;
uint64_t akey_val = 200;
uint32_t update_var0 = 0x1234;
uint32_t update_var1 = 0x6789;
uint32_t update_var2 = 0xbcdf;
uint32_t flags = DAOS_GET_DKEY | DAOS_GET_AKEY | DAOS_GET_RECX | DAOS_GET_MAX;
int rc;

FAULT_INJECTION_REQUIRED();

print_message("iteration does not return aborted DTX\n");

if (!test_runable(arg, dts_dtx_replica_cnt))
return;

oid = daos_test_oid_gen(arg->coh, dts_dtx_class, DAOS_OT_MULTI_UINT64, 0, arg->myrank);
rc = daos_obj_open(arg->coh, oid, DAOS_OO_RW, &oh, NULL);
assert_rc_equal(rc, 0);

d_iov_set(&dkey, &dkey_val, sizeof(uint64_t));
d_iov_set(&akey, &akey_val, sizeof(uint64_t));
iod.iod_name = akey;
iod.iod_type = DAOS_IOD_ARRAY;
iod.iod_size = sizeof(update_var0);

d_iov_set(&val_iov[0], &update_var0, sizeof(update_var0));
d_iov_set(&val_iov[1], &update_var1, sizeof(update_var1));
sgl.sg_nr = 2;
sgl.sg_iovs = val_iov;
recx[0].rx_idx = 30;
recx[0].rx_nr = 1;
recx[1].rx_idx = 50;
recx[1].rx_nr = 1;
iod.iod_nr = 2;
iod.iod_recxs = recx;

rc = daos_obj_update(oh, DAOS_TX_NONE, 0, &dkey, 1, &iod, &sgl, NULL);
assert_rc_equal(rc, 0);

dkey_val = 0;
akey_val = 0;
rc = daos_obj_query_key(oh, DAOS_TX_NONE, flags, &dkey, &akey, &recx[0], NULL);
assert_rc_equal(rc, 0);

assert_int_equal(*(uint64_t *)dkey.iov_buf, 100);
assert_int_equal(*(uint64_t *)akey.iov_buf, 200);
assert_int_equal(recx[0].rx_idx, 50);
assert_int_equal(recx[0].rx_nr, 1);

par_barrier(PAR_COMM_WORLD);
if (arg->myrank == 0)
/* Simulate the case of TX IO error on the shard_1. */
daos_debug_set_params(arg->group, -1, DMG_KEY_FAIL_LOC,
DAOS_DTX_FAIL_IO | DAOS_FAIL_ALWAYS, 0, NULL);
par_barrier(PAR_COMM_WORLD);

d_iov_set(&val_iov[0], &update_var2, sizeof(update_var2));
sgl.sg_nr = 1;
sgl.sg_iovs = &val_iov[0];
recx[0].rx_idx = 70;
recx[0].rx_nr = 1;
iod.iod_nr = 1;
iod.iod_recxs = &recx[0];

/* Update the same dkey & akey with higher index. */
dkey_val = 100;
akey_val = 200;
rc = daos_obj_update(oh, DAOS_TX_NONE, 0, &dkey, 1, &iod, &sgl, NULL);
assert_rc_equal(rc, -DER_IO);

dkey_val = 0;
akey_val = 0;
rc = daos_obj_query_key(oh, DAOS_TX_NONE, flags, &dkey, &akey, &recx[0], NULL);
assert_rc_equal(rc, 0);

/* Since the 2nd update failed, query should return old value. */
assert_int_equal(*(uint64_t *)dkey.iov_buf, 100);
assert_int_equal(*(uint64_t *)akey.iov_buf, 200);
assert_int_equal(recx[0].rx_idx, 50);
assert_int_equal(recx[0].rx_nr, 1);

rc = daos_obj_close(oh, NULL);
assert_rc_equal(rc, 0);

par_barrier(PAR_COMM_WORLD);
if (arg->myrank == 0)
daos_debug_set_params(arg->group, -1, DMG_KEY_FAIL_LOC, 0, 0, NULL);
par_barrier(PAR_COMM_WORLD);
}

static int
dtx_base_rf0_setup(void **state)
{
Expand Down Expand Up @@ -947,6 +1049,8 @@ static const struct CMUnitTest dtx_tests[] = {
dtx_20, dtx_base_rf1_setup, rebuild_sub_teardown},
{"DTX21: do not abort partially committed DTX",
dtx_21, dtx_base_rf0_setup, rebuild_sub_teardown},
{"DTX22: iteration does not return aborted DTX",
dtx_22, NULL, test_case_teardown},
};

static int
Expand Down
69 changes: 38 additions & 31 deletions src/vos/evt_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,22 +306,6 @@ evt_iter_move(struct evt_context *tcx, struct evt_iterator *iter)
return rc;
}

static int
evt_iter_skip(struct evt_context *tcx, struct evt_iterator *iter)
{
struct evt_entry_array *enta;
struct evt_entry *entry;

if (iter->it_options & (EVT_ITER_SKIP_HOLES | EVT_ITER_SKIP_DATA)) {
enta = iter->it_entries;
entry = evt_ent_array_get(enta, iter->it_index);

if (should_skip(entry, iter))
return evt_iter_move(tcx, iter);
}
return 0;
}

static int
evt_iter_probe_sorted(struct evt_context *tcx, struct evt_iterator *iter,
int opc, const struct evt_rect *rect,
Expand Down Expand Up @@ -369,31 +353,35 @@ evt_iter_probe_sorted(struct evt_context *tcx, struct evt_iterator *iter,

if (opc == EVT_ITER_FIRST) {
index = iter->it_forward ? 0 : enta->ea_ent_nr - 1;
iter->it_index = index;
/* Mark the last entry */
entry = evt_ent_array_get(enta, enta->ea_ent_nr - 1 - index);
entry->en_visibility |= EVT_LAST;
goto out;
}

if (opc != EVT_ITER_FIND) {
} else if (opc != EVT_ITER_FIND) {
D_ERROR("Unknown op code for evt iterator: %d\n", opc);
return -DER_NOSYS;
} else {
/** If entry doesn't exist, it will return next entry */
index = evt_iter_probe_find(iter, rect);
if (index == -1)
return -DER_NONEXIST;
}

/** If entry doesn't exist, it will return next entry */
index = evt_iter_probe_find(iter, rect);
if (index == -1)
return -DER_NONEXIST;

iter->it_index = index;
entry = evt_ent_array_get(iter->it_entries, index);
entry = evt_ent_array_get(enta, index);

if (rect != NULL)
D_DEBUG(DB_TRACE, "probe ent "DF_EXT" Update ent "DF_EXT"\n",
DP_EXT(&rect->rc_ex), DP_EXT(&entry->en_sel_ext));

if (entry->en_avail_rc < 0)
return entry->en_avail_rc;

D_DEBUG(DB_TRACE, "probe ent "DF_EXT" Update ent "DF_EXT"\n",
DP_EXT(&rect->rc_ex), DP_EXT(&entry->en_sel_ext));
out:
iter->it_state = EVT_ITER_READY;
return evt_iter_skip(tcx, iter);

if (entry->en_avail_rc == ALB_UNAVAILABLE || should_skip(entry, iter))
return evt_iter_move(tcx, iter);

return 0;
}

static void
Expand Down Expand Up @@ -470,8 +458,27 @@ evt_iter_probe(daos_handle_t ih, enum evt_iter_opc opc,
iter->it_state = EVT_ITER_FINI;
rc = -DER_NONEXIST;
} else {
struct evt_trace *trace;
struct evt_node *nd;
struct evt_node_entry *ne;
struct evt_desc *desc;

trace = &tcx->tc_trace[tcx->tc_depth - 1];
nd = evt_off2node(tcx, trace->tr_node);
ne = evt_node_entry_at(tcx, nd, trace->tr_at);
desc = evt_off2desc(tcx, ne->ne_child);

rc = evt_desc_log_status(tcx, ne->ne_rect.rd_epc, desc, evt_iter_intent(iter));
if (rc < 0)
goto out;

iter->it_state = EVT_ITER_READY;
iter->it_skip_move = 0;

if (rc == ALB_UNAVAILABLE)
return evt_iter_move(tcx, iter);

rc = 0;
}
out:
return rc;
Expand Down

0 comments on commit 14d43dc

Please sign in to comment.