Skip to content
Open
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
12 changes: 12 additions & 0 deletions src/include/daos_srv/vos.h
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,18 @@ vos_ioh2ci(daos_handle_t ioh);
uint32_t
vos_ioh2ci_nr(daos_handle_t ioh);

/**
* Get the actual stored epoch of the single value fetched by vos_fetch_begin().
* Only meaningful for DAOS_IOD_SINGLE akeys after a successful fetch; returns 0
* if no single value was found (hole, -DER_NONEXIST, or array akey fetch).
*
* \param ioh [IN] The I/O handle.
*
* \return Actual stored epoch, or 0 if no SV was found.
*/
daos_epoch_t
vos_ioh2sv_epoch(daos_handle_t ioh);

/**
* Get the scatter/gather list associated with a given I/O descriptor.
*
Expand Down
8 changes: 8 additions & 0 deletions src/utils/ddb/ddb.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ struct dtx_aggr_options {
char *cmt_date;
};

struct csum_dump_options {
char *path;
char *dst;
daos_epoch_t epoch;
};

/* Run commands ... */
int
ddb_run_ls(struct ddb_ctx *ctx, struct ls_options *opt);
Expand Down Expand Up @@ -240,5 +246,7 @@ int
ddb_run_prov_mem(struct ddb_ctx *ctx, struct prov_mem_options *opt);
int
ddb_run_dtx_aggr(struct ddb_ctx *ctx, struct dtx_aggr_options *opt);
int
ddb_run_csum_dump(struct ddb_ctx *ctx, struct csum_dump_options *opt);

#endif /* __DDB_RUN_CMDS_H */
308 changes: 308 additions & 0 deletions src/utils/ddb/ddb_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,314 @@ ddb_run_value_dump(struct ddb_ctx *ctx, struct value_dump_options *opt)
return rc;
}

static void
print_csum_bufs(struct ddb_ctx *ctx, struct dcs_csum_info *ci)
{
uint8_t *csum_buf;
int i;

ddb_print(ctx, "0x");
csum_buf = ci_idx2csum(ci, 0);
for (i = 0; i < ci->cs_len; i++)
ddb_printf(ctx, "%02" PRIx8, csum_buf[i]);

for (i = 1; i < ci->cs_nr; i++) {
int j;

csum_buf = ci_idx2csum(ci, i);
ddb_print(ctx, ", 0x");
for (j = 0; j < ci->cs_len; j++)
ddb_printf(ctx, "%02" PRIx8, csum_buf[j]);
}
ddb_print(ctx, "\n");
}

struct dump_csum_args {
struct ddb_ctx *dca_ctx;
struct dv_indexed_tree_path *dca_vtp;
char *dca_dst_path;
};

static int
print_csum_recx(void *cb_args, struct daos_recx_ep_list *recx_rel, daos_epoch_t sv_epoch,
struct dcs_ci_list *cil)
{
struct dump_csum_args *args;
struct ddb_ctx *ctx;
struct dcs_csum_info *ci;
struct hash_ft *hf;
struct daos_recx_ep *rep;
uint32_t chunk_sz;
int i;

args = cb_args;
ctx = args->dca_ctx;

if (cil->dcl_csum_infos_nr == 0) {
ddb_print(ctx, "No checksum at ");
itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
return 0;
}

D_ASSERT(recx_rel != NULL);
D_ASSERT(cil->dcl_csum_infos_nr == recx_rel->re_nr);

ci = dcs_csum_info_get(cil, 0);
D_ASSERT(ci_is_valid(ci));
rep = &recx_rel->re_items[0];
hf = daos_mhash_type2algo(ci->cs_type);
chunk_sz = ci->cs_chunksize;

itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
ddb_printf(ctx,
"Checksum Type: %s, Checksum Length: %" PRIu16 ", Chunk Size: %" PRIu32
", Record Extent(s):\n",
hf->cf_name, ci->cs_len, chunk_sz);

ddb_printf(ctx,
"- Record Indexes: {%" PRIu64 "-%" PRIu64 "}, Record Size: %" PRIu32
", Epoch: %" PRIu64 ", Checksum Value(s): ",
rep->re_recx.rx_idx, rep->re_recx.rx_idx + rep->re_recx.rx_nr - 1,
rep->re_rec_size, rep->re_ep);
print_csum_bufs(ctx, ci);

for (i = 1; i < cil->dcl_csum_infos_nr; i++) {
ci = dcs_csum_info_get(cil, i);
D_ASSERT(ci_is_valid(ci));
rep = &recx_rel->re_items[i];

ddb_printf(ctx,
"- Record Indexes: {%" PRIu64 "-%" PRIu64 "}, Record Size: %" PRIu32
", Epoch: %" PRIu64 ", Checksum Value(s): ",
rep->re_recx.rx_idx, rep->re_recx.rx_idx + rep->re_recx.rx_nr - 1,
rep->re_rec_size, rep->re_ep);
print_csum_bufs(ctx, ci);
}

return 0;
}

static int
append_csums2value(d_iov_t *value, struct dcs_csum_info *ci)
{
uint8_t *buf;
size_t new_len;
int i;

new_len = value->iov_len + (ci->cs_nr * ci->cs_len);
D_REALLOC(buf, value->iov_buf, value->iov_buf_len, new_len);
if (buf == NULL)
return -DER_NOMEM;
value->iov_buf = buf;
value->iov_buf_len = new_len;

for (i = 0; i < ci->cs_nr; i++) {
uint8_t *csum_buf = ci_idx2csum(ci, i);

memcpy((uint8_t *)value->iov_buf + value->iov_len, csum_buf, ci->cs_len);
value->iov_len += ci->cs_len;
}

return 0;
}

static int
write_file_csum_recx(void *cb_args, struct daos_recx_ep_list *recx_rel, daos_epoch_t sv_epoch,
struct dcs_ci_list *cil)
{
struct dump_csum_args *args;
struct ddb_ctx *ctx;
struct dcs_csum_info *ci;
struct hash_ft *hf;
struct daos_recx_ep *rep;
uint32_t chunk_sz;
d_iov_t value = {0};
int i;
int rc;

args = cb_args;
ctx = args->dca_ctx;

if (cil->dcl_csum_infos_nr == 0) {
ddb_print(ctx, "No checksum at ");
itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
rc = 0;
goto out;
}

D_ASSERT(recx_rel != NULL);
D_ASSERT(cil->dcl_csum_infos_nr == recx_rel->re_nr);

ci = dcs_csum_info_get(cil, 0);
D_ASSERT(ci_is_valid(ci));
rep = &recx_rel->re_items[0];
hf = daos_mhash_type2algo(ci->cs_type);
chunk_sz = ci->cs_chunksize;

itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
ddb_printf(ctx,
"Dumping checksum(s) (Type: %s, Length: %" PRIu16 ", Chunk Size: %" PRIu32
") at %s\n",
hf->cf_name, ci->cs_len, chunk_sz, args->dca_dst_path);

ddb_printf(ctx,
"- Record Indexes: {%" PRIu64 "-%" PRIu64 "}, Record Size: %" PRIu32
", Epoch: %" PRIu64 "\n",
rep->re_recx.rx_idx, rep->re_recx.rx_idx + rep->re_recx.rx_nr - 1,
rep->re_rec_size, rep->re_ep);
rc = append_csums2value(&value, ci);
if (!SUCCESS(rc))
goto out_buf;

for (i = 1; i < cil->dcl_csum_infos_nr; i++) {
ci = dcs_csum_info_get(cil, i);
D_ASSERT(ci_is_valid(ci));
rep = &recx_rel->re_items[i];

ddb_printf(ctx,
"- Record Indexes: {%" PRIu64 "-%" PRIu64 "}, Record Size: %" PRIu32
", Epoch: %" PRIu64 "\n",
rep->re_recx.rx_idx, rep->re_recx.rx_idx + rep->re_recx.rx_nr - 1,
rep->re_rec_size, rep->re_ep);
rc = append_csums2value(&value, ci);
if (!SUCCESS(rc))
goto out_buf;
}

rc = ctx->dc_io_ft.ddb_write_file(args->dca_dst_path, &value);

out_buf:
D_FREE(value.iov_buf);
out:
return rc;
}

static int
print_csum_sv(void *cb_args, struct daos_recx_ep_list *recx_rel, daos_epoch_t sv_epoch,
struct dcs_ci_list *cil)
{
struct dump_csum_args *args;
struct ddb_ctx *ctx;
struct dcs_csum_info *ci;
struct hash_ft *hf;

args = cb_args;
ctx = args->dca_ctx;

if (cil->dcl_csum_infos_nr == 0) {
ddb_print(ctx, "No checksum at ");
itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
return 0;
}
D_ASSERT(cil->dcl_csum_infos_nr == 1);

ci = dcs_csum_info_get(cil, 0);
D_ASSERT(ci_is_valid(ci));
D_ASSERT(ci->cs_nr == 1);
hf = daos_mhash_type2algo(ci->cs_type);

itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
ddb_printf(ctx, "Type: %s, Length: %" PRIu16 ", Epoch: %" PRIu64 ", Value: ", hf->cf_name,
ci->cs_len, sv_epoch);
print_csum_bufs(ctx, ci);

return 0;
}

static int
write_file_csum_sv(void *cb_args, struct daos_recx_ep_list *recx_rel, daos_epoch_t sv_epoch,
struct dcs_ci_list *cil)
{
struct dump_csum_args *args;
struct ddb_ctx *ctx;
struct dcs_csum_info *ci;
struct hash_ft *hf;
d_iov_t value;
int rc;

args = cb_args;
ctx = args->dca_ctx;

D_ASSERT(ctx->dc_io_ft.ddb_write_file);

if (cil->dcl_csum_infos_nr == 0) {
ddb_print(ctx, "No checksum at ");
itp_print_full(ctx, args->dca_vtp);
ddb_print(ctx, "\n");
rc = 0;
goto out;
}
D_ASSERT(cil->dcl_csum_infos_nr == 1);

ci = dcs_csum_info_get(cil, 0);
D_ASSERT(ci_is_valid(ci));
D_ASSERT(ci->cs_nr == 1);
hf = daos_mhash_type2algo(ci->cs_type);

value.iov_buf = ci_idx2csum(ci, 0);
value.iov_len = ci->cs_len;
value.iov_buf_len = ci->cs_buf_len;

ddb_printf(ctx,
"Dumping checksum (type: %s, length: %" PRIu16 ", epoch: %" PRIu64 ") to %s\n",
hf->cf_name, ci->cs_len, sv_epoch, args->dca_dst_path);
rc = ctx->dc_io_ft.ddb_write_file(args->dca_dst_path, &value);

out:
return rc;
}

int
ddb_run_csum_dump(struct ddb_ctx *ctx, struct csum_dump_options *opt)
{
struct dv_indexed_tree_path itp = {0};
struct dv_tree_path vtp;
struct dump_csum_args dca = {0};
dv_dump_csum_cb cb = NULL;
int rc;

if (!opt->path) {
ddb_error(ctx, "A VOS path to dump is required.\n");
rc = -DER_INVAL;
goto out;
}

rc = init_path(ctx, opt->path, &itp);
if (!SUCCESS(rc))
goto out;

if (!itp_has_value(&itp)) {
ddb_errorf(ctx, "Path [%s] is incomplete.\n", opt->path);
rc = -DDBER_INCOMPLETE_PATH_VALUE;
goto out_itp;
}

if (opt->dst && opt->dst[0] != '\0')
cb = (itp_has_recx(&itp)) ? write_file_csum_recx : write_file_csum_sv;
else
cb = (itp_has_recx(&itp)) ? print_csum_recx : print_csum_sv;

dca.dca_dst_path = opt->dst;
dca.dca_ctx = ctx;
dca.dca_vtp = &itp;

itp_to_vos_path(&itp, &vtp);

rc = dv_dump_csum(ctx->dc_poh, &vtp, opt->epoch, cb, &dca);

out_itp:
itp_free(&itp);

out:
return rc;
}

static int
dump_ilog_entry_cb(void *cb_arg, struct ddb_ilog_entry *entry)
{
Expand Down
6 changes: 2 additions & 4 deletions src/utils/ddb/ddb_vos.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,7 @@ dump_csum_sv(daos_handle_t coh, daos_key_t *dkey, daos_unit_oid_t *oid, daos_iod
}

cil = vos_ioh2ci(ioh);

cb_rc = dump_cb(cb_arg, NULL, cil);
cb_rc = dump_cb(cb_arg, NULL, vos_ioh2sv_epoch(ioh), cil);
if (!SUCCESS(cb_rc))
D_DEBUG(DB_IO, "Csum dump callback for " DF_UOID " returned: " DF_RC "\n",
DP_UOID(*oid), DP_RC(cb_rc));
Expand Down Expand Up @@ -1146,8 +1145,7 @@ dump_csum_recx(daos_handle_t coh, daos_key_t *dkey, daos_unit_oid_t *oid, daos_i

cil = vos_ioh2ci(ioh);
rel = vos_ioh2recx_list(ioh);

cb_rc = dump_cb(cb_arg, rel, cil);
cb_rc = dump_cb(cb_arg, rel, 0, cil);
if (!SUCCESS(cb_rc))
D_DEBUG(DB_IO, "Csum dump callback for " DF_UOID " returned: " DF_RC "\n",
DP_UOID(*oid), DP_RC(cb_rc));
Expand Down
Loading
Loading