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).

Signed-off-by: Fan Yong <fan.yong@intel.com>
  • Loading branch information
Nasf-Fan committed May 23, 2024
1 parent 6bbfb3c commit c8e154c
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 17 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
44 changes: 27 additions & 17 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 @@ -392,8 +376,15 @@ evt_iter_probe_sorted(struct evt_context *tcx, struct evt_iterator *iter,
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:
if (entry->en_avail_rc < 0)
return entry->en_avail_rc;

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 +461,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 c8e154c

Please sign in to comment.