Skip to content

Commit

Permalink
improve json parsing of bdev params with spdk api
Browse files Browse the repository at this point in the history
Required-githooks: true

Signed-off-by: Tom Nabarro <[email protected]>
  • Loading branch information
tanabarr committed Nov 17, 2023
1 parent cd320fc commit 6f3eca8
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 42 deletions.
134 changes: 134 additions & 0 deletions src/bio/bio_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,3 +935,137 @@ bio_read_rpc_srv_settings(const char *nvme_conf, bool *enable, const char **sock
rc = 0;
return rc;
}

static int
json_decode_bdev_str(struct spdk_json_val *obj, const char *key, char **dst)
{
struct spdk_json_val *val = NULL;
int rc;

rc = spdk_json_find_string(obj, key, NULL, &val);
if (rc < 0) {
D_ERROR("Failed to find string value '%s': %s\n", key, strerror(-rc));
return -DER_INVAL;
}

rc = spdk_json_decode_string(val, dst);
if (rc < 0) {
D_ERROR("Failed to decode string value for '%s': %s\n", key, strerror(-rc));
return -DER_INVAL;
}

return 0;
}

static struct spdk_json_object_decoder nvme_ns_decoders[] = {
{"id", offsetof(struct ns_t, id), spdk_json_decode_uint32},
};

/**
* Fetch bdev controller parameters from spdk_bdev_dump_info_json output.
*
* \param[out] *b_info Device info struct to populate
* \param[in] json Raw JSON to parse
* \param[in] json_size Number of JSON chars
*
* \returns Zero on success, negative on failure (DER)
*/
int
bio_decode_bdev_params(struct bio_dev_info *b_info, const void *json, int json_size)
{
struct spdk_json_val *values = NULL;
struct spdk_json_val *ctrlr_data = NULL;
struct spdk_json_val *ns_data = NULL;
void *end;
ssize_t values_cnt;
char *tmp = NULL;
ssize_t rc;
char *end1 = NULL;

/* Trim chars to get single valid "nvme" object from array. */
tmp = strstr(json, "{");
if (tmp == NULL)
return -DER_INVAL;
end1 = strchr(tmp, ']');
if (end1 == NULL)
return -DER_INVAL;
*end1 = '\0';

D_INFO("input JSON: %s\n", tmp);
rc = spdk_json_parse((void *)tmp, end1 - tmp, NULL, 0, &end,
SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
if (rc < 0) {
D_ERROR("Parsing config failed: %s\n", strerror(-rc));
return -DER_INVAL;
}
D_INFO("input JSON Count: %ld\n", rc);

values_cnt = rc;
D_ALLOC_ARRAY(values, values_cnt);
if (values == NULL)
return -DER_NOMEM;

rc = spdk_json_parse((void *)tmp, end1 - tmp, values, values_cnt, &end,
SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
if (rc != values_cnt) {
D_ERROR("Parsing config failed, want %zd values got %zd\n", values_cnt, rc);
D_GOTO(out, rc = -DER_INVAL);
}

D_INFO("JSON type: %d\n", values->type);

rc = json_decode_bdev_str(values, "pci_address", &b_info->bdi_traddr);
if (rc < 0) {
D_ERROR("Failed to decode JSON string value for pci_address: %s\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = spdk_json_find(values, "ctrlr_data", NULL, &ctrlr_data, SPDK_JSON_VAL_OBJECT_BEGIN);
if ((rc < 0) && (ctrlr_data == NULL)) {
D_ERROR("Failed to find ctrlr_data JSON object: %s\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = json_decode_bdev_str(ctrlr_data, "model_number", &b_info->bdi_ctrlr->model);
if (rc < 0) {
D_ERROR("Failed to decode JSON string value for model_number: %s\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = json_decode_bdev_str(ctrlr_data, "serial_number", &b_info->bdi_ctrlr->serial);
if (rc < 0) {
D_ERROR("Failed to decode JSON string value for serial_number: %s\n",
strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = json_decode_bdev_str(ctrlr_data, "firmware_revision", &b_info->bdi_ctrlr->fw_rev);
if (rc < 0) {
D_ERROR("Failed to decode JSON string value for firmware_revision: %s\n",
strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = json_decode_bdev_str(ctrlr_data, "vendor_id", &b_info->bdi_ctrlr->vendor_id);
if (rc < 0) {
D_ERROR("Failed to decode JSON string value for vendor_id: %s\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = spdk_json_find(values, "ns_data", NULL, &ns_data, SPDK_JSON_VAL_OBJECT_BEGIN);
if ((rc < 0) && (ns_data == NULL)) {
D_ERROR("Failed to find ns_data JSON object: %s\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}

rc = spdk_json_decode_object(ns_data, nvme_ns_decoders, SPDK_COUNTOF(nvme_ns_decoders),
&b_info->bdi_ctrlr->nss);
if (rc < 0) {
D_ERROR("Failed to decode 'id' entry (%s)\n", strerror(-rc));
D_GOTO(out, rc = -DER_INVAL);
}
out:
D_FREE(values);

return rc;
}
100 changes: 58 additions & 42 deletions src/bio/bio_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ bio_replace_dev(struct bio_xs_context *xs_ctxt, uuid_t old_dev_id,
static char *json_prefix = NULL;

static int
json_write_cb(void *cb_ctx, const void *data, size_t size)
json_write_str_cb(void *cb_ctx, const void *data, size_t size)
{
char *tmp, *end, **buf_ptr = cb_ctx;

Expand All @@ -474,9 +474,10 @@ json_write_cb(void *cb_ctx, const void *data, size_t size)
if (size <= strlen(json_prefix))
return 0;

D_DEBUG(DB_MGMT, "%s json: %s\n", json_prefix, (char *)data);

tmp = strstr(data, json_prefix);
if (tmp) {

tmp += strlen(json_prefix);
end = strchr(tmp, '"');
if (end == NULL)
Expand All @@ -493,7 +494,7 @@ json_write_cb(void *cb_ctx, const void *data, size_t size)
}

static int
find_in_bdev_json(struct spdk_bdev *bdev, char **buf_ptr, char *prefix)
find_bdev_json_str(struct spdk_bdev *bdev, char **buf_ptr, char *prefix)
{
struct spdk_json_write_ctx *json;
int rc;
Expand All @@ -503,7 +504,7 @@ find_in_bdev_json(struct spdk_bdev *bdev, char **buf_ptr, char *prefix)

json_prefix = prefix;

json = spdk_json_write_begin(json_write_cb, buf_ptr, SPDK_JSON_WRITE_FLAG_FORMATTED);
json = spdk_json_write_begin(json_write_str_cb, buf_ptr, SPDK_JSON_WRITE_FLAG_FORMATTED);
if (json == NULL) {
D_ERROR("Failed to alloc SPDK json context\n");
D_GOTO(out, rc = -DER_NOMEM);
Expand Down Expand Up @@ -531,6 +532,40 @@ find_in_bdev_json(struct spdk_bdev *bdev, char **buf_ptr, char *prefix)
return rc;
}

static int
json_write_cb(void *cb_ctx, const void *json, size_t json_size)
{
struct bio_dev_info *b_info = cb_ctx;

return bio_decode_bdev_params(b_info, json, (int)json_size);
}

static int
json_find_bdev_params(struct spdk_bdev *bdev, struct bio_dev_info *b_info)
{
struct spdk_json_write_ctx *json;
int rc;

json = spdk_json_write_begin(json_write_cb, b_info, SPDK_JSON_WRITE_FLAG_FORMATTED);
if (json == NULL) {
D_ERROR("Failed to alloc SPDK json context\n");
return -DER_NOMEM;
}

rc = spdk_bdev_dump_info_json(bdev, json);
if (rc != 0) {
D_ERROR("Failed to dump config from SPDK bdev (%s)\n", spdk_strerror(-rc));
return daos_errno2der(-rc);
}

rc = spdk_json_write_end(json);
if (rc != 0) {
D_ERROR("Failed to write JSON (%s)\n", spdk_strerror(-rc));
return daos_errno2der(-rc);
}

return rc;
}

int
fill_in_traddr(struct bio_dev_info *b_info, char *dev_name)
Expand All @@ -551,7 +586,7 @@ fill_in_traddr(struct bio_dev_info *b_info, char *dev_name)
if (get_bdev_type(bdev) != BDEV_CLASS_NVME)
return 0;

rc = find_in_bdev_json(bdev, &b_info->bdi_traddr, "traddr\": \"");
rc = find_bdev_json_str(bdev, &b_info->bdi_traddr, "traddr\": \"");
if (rc != 0) {
D_ERROR("Failed to get traddr for %s\n", dev_name);
return rc;
Expand All @@ -564,7 +599,7 @@ static struct bio_dev_info *
alloc_dev_info(uuid_t dev_id, char *dev_name, struct smd_dev_info *s_info)
{
struct bio_dev_info *info;
int tgt_cnt = 0, i, rc;
int tgt_cnt = 0, i;

D_ALLOC_PTR(info);
if (info == NULL)
Expand All @@ -577,14 +612,6 @@ alloc_dev_info(uuid_t dev_id, char *dev_name, struct smd_dev_info *s_info)
info->bdi_flags |= NVME_DEV_FL_FAULTY;
}

if (dev_name != NULL) {
rc = fill_in_traddr(info, dev_name);
if (rc != 0) {
bio_free_dev_info(info);
return NULL;
}
}

if (tgt_cnt != 0) {
D_ALLOC_ARRAY(info->bdi_tgts, tgt_cnt);
if (info->bdi_tgts == NULL) {
Expand Down Expand Up @@ -691,8 +718,9 @@ static int
alloc_ctrlr_info(uuid_t dev_id, char *dev_name, struct bio_dev_info *b_info)
{
struct spdk_bdev *bdev;
struct ctrlr_t *w_ctrlr;
int rc;
uint32_t blk_sz;
uint64_t nr_blks;
int rc;

D_ASSERT(b_info != NULL);
D_ASSERT(b_info->bdi_ctrlr == NULL);
Expand All @@ -711,44 +739,32 @@ alloc_ctrlr_info(uuid_t dev_id, char *dev_name, struct bio_dev_info *b_info)
if (get_bdev_type(bdev) != BDEV_CLASS_NVME)
return 0;

D_DEBUG(DB_MGMT, "fetching %s controller details\n", b_info->bdi_traddr);

D_ALLOC_PTR(b_info->bdi_ctrlr);
if (b_info->bdi_ctrlr == NULL)
return -DER_NOMEM;
w_ctrlr = b_info->bdi_ctrlr;

rc = find_in_bdev_json(bdev, &w_ctrlr->model, "model_number\": \"");
if (rc != 0) {
D_ERROR("Failed to get model_number for %s\n", dev_name);
return rc;
}
D_ALLOC_PTR(b_info->bdi_ctrlr->nss);
if (b_info->bdi_ctrlr->nss == NULL)
return -DER_NOMEM;

rc = find_in_bdev_json(bdev, &w_ctrlr->serial, "serial_number\": \"");
if (rc != 0) {
D_ERROR("Failed to get serial_number for %s\n", dev_name);
return rc;
}
/* Namespace capacity by direct query of SPDK bdev object */
blk_sz = spdk_bdev_get_block_size(bdev);
nr_blks = spdk_bdev_get_num_blocks(bdev);
b_info->bdi_ctrlr->nss->size = nr_blks * (uint64_t)blk_sz;

rc = find_in_bdev_json(bdev, &w_ctrlr->fw_rev, "firmware_revision\": \"");
/* Controller details and namespace ID by parsing SPDK bdev JSON info */
rc = json_find_bdev_params(bdev, b_info);
if (rc != 0) {
D_ERROR("Failed to get firmware_revision for %s\n", dev_name);
D_ERROR("Failed to get bdev json params for %s\n", dev_name);
return rc;
}

rc = find_in_bdev_json(bdev, &w_ctrlr->vendor_id, "vendor_id\": \"");
if (rc != 0) {
D_ERROR("Failed to get vendor_id for %s\n", dev_name);
return rc;
}
if (w_ctrlr->vendor_id == NULL) {
D_ERROR("Nil value returned for vendor_id on %s\n", dev_name);
return -DER_INVAL;
}
D_DEBUG(DB_MGMT, "fetched %s controller details\n", b_info->bdi_traddr);
D_DEBUG(DB_MGMT, "namespace %d of size %lu\n", b_info->bdi_ctrlr->nss->id,
b_info->bdi_ctrlr->nss->size);

/* Fetch socket ID and PCI device type by enumerating spdk_pci_device list */

rc = fetch_pci_dev_info(w_ctrlr, b_info->bdi_traddr);
rc = fetch_pci_dev_info(b_info->bdi_ctrlr, b_info->bdi_traddr);
if (rc != 0) {
return rc;
}
Expand Down
2 changes: 2 additions & 0 deletions src/bio/bio_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,4 +667,6 @@ int bio_add_allowed_alloc(const char *nvme_conf, struct spdk_env_opts *opts, int
int bio_set_hotplug_filter(const char *nvme_conf);
int bio_read_accel_props(const char *nvme_conf);
int bio_read_rpc_srv_settings(const char *nvme_conf, bool *enable, const char **sock_addr);
int
bio_decode_bdev_params(struct bio_dev_info *b_info, const void *json, int json_size);
#endif /* __BIO_INTERNAL_H__ */

0 comments on commit 6f3eca8

Please sign in to comment.