diff --git a/lib/vhost/vhost_rpc.c b/lib/vhost/vhost_rpc.c index 878e54cd2..e7e96ff83 100644 --- a/lib/vhost/vhost_rpc.c +++ b/lib/vhost/vhost_rpc.c @@ -40,6 +40,7 @@ #include "spdk/scsi.h" #include "spdk/vhost.h" #include "vhost_internal.h" +#include "spdk/bdev.h" static void json_scsi_dev_write(struct spdk_json_write_ctx *ctx, struct spdk_scsi_dev *dev) @@ -84,7 +85,6 @@ spdk_rpc_get_vhost_scsi_controllers(struct spdk_jsonrpc_server_conn *conn, struct spdk_vhost_dev *vdev = NULL; struct spdk_scsi_dev *dev; uint32_t i; - char buf[32]; if (params != NULL) { spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, @@ -92,6 +92,10 @@ spdk_rpc_get_vhost_scsi_controllers(struct spdk_jsonrpc_server_conn *conn, return; } + if (id == NULL) { + return; + } + w = spdk_jsonrpc_begin_result(conn, id); spdk_json_write_array_begin(w); while ((vdev = spdk_vhost_dev_next(vdev)) != NULL) { @@ -105,8 +109,7 @@ spdk_rpc_get_vhost_scsi_controllers(struct spdk_jsonrpc_server_conn *conn, spdk_json_write_string(w, spdk_vhost_dev_get_name(vdev)); spdk_json_write_name(w, "cpu_mask"); - snprintf(buf, sizeof(buf), "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev)); - spdk_json_write_string(w, buf); + spdk_json_write_string_fmt(w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev)); spdk_json_write_name(w, "scsi_devs"); spdk_json_write_array_begin(w); @@ -181,9 +184,11 @@ spdk_rpc_construct_vhost_scsi_controller(struct spdk_jsonrpc_server_conn *conn, free_rpc_vhost_scsi_ctrlr(&req); - w = spdk_jsonrpc_begin_result(conn, id); - spdk_json_write_bool(w, true); - spdk_jsonrpc_end_result(conn, w); + if (id != NULL) { + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(conn, w); + } return; invalid: free_rpc_vhost_scsi_ctrlr(&req); @@ -363,3 +368,176 @@ invalid: spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); } SPDK_RPC_REGISTER("remove_vhost_scsi_dev", spdk_rpc_remove_vhost_scsi_dev) + +struct rpc_vhost_blk_ctrlr { + char *ctrlr; + char *dev_name; + char *cpumask; +}; + +static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = { + {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, + {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string }, + {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true}, +}; + +static void +free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req) +{ + free(req->ctrlr); + free(req->dev_name); + free(req->cpumask); +} + +static void +spdk_rpc_construct_vhost_blk_controller(struct spdk_jsonrpc_server_conn *conn, + const struct spdk_json_val *params, + const struct spdk_json_val *id) +{ + struct rpc_vhost_blk_ctrlr req = {0}; + struct spdk_json_write_ctx *w; + int rc; + uint64_t cpumask; + + if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr, + SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr), + &req)) { + SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); + rc = -EINVAL; + goto invalid; + } + + cpumask = spdk_app_get_core_mask(); + if (req.cpumask != NULL && spdk_vhost_parse_core_mask(req.cpumask, &cpumask)) { + rc = -EINVAL; + goto invalid; + } + + rc = spdk_vhost_blk_construct(req.ctrlr, cpumask, req.dev_name); + if (rc < 0) { + goto invalid; + } + + free_rpc_vhost_blk_ctrlr(&req); + + if (id != NULL) { + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(conn, w); + } + + return; +invalid: + free_rpc_vhost_blk_ctrlr(&req); + spdk_jsonrpc_send_error_response(conn, id, + SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); + +} +SPDK_RPC_REGISTER("construct_vhost_blk_controller", spdk_rpc_construct_vhost_blk_controller) + +struct rpc_remove_vhost_blk_ctrlr { + char *ctrlr; +}; + +static const struct spdk_json_object_decoder rpc_remove_vhost_blk_ctrlr[] = { + {"ctrlr", offsetof(struct rpc_remove_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string }, +}; + +static void +free_rpc_remove_vhost_blk_ctrlr(struct rpc_remove_vhost_blk_ctrlr *req) +{ + free(req->ctrlr); +} + +static void +spdk_rpc_remove_vhost_blk_controller(struct spdk_jsonrpc_server_conn *conn, + const struct spdk_json_val *params, + const struct spdk_json_val *id) +{ + struct rpc_remove_vhost_blk_ctrlr req = {NULL}; + struct spdk_json_write_ctx *w; + struct spdk_vhost_dev *vdev; + int rc; + + if (spdk_json_decode_object(params, rpc_remove_vhost_blk_ctrlr, + SPDK_COUNTOF(rpc_remove_vhost_blk_ctrlr), &req)) { + SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); + rc = -EINVAL; + goto invalid; + } + + if (!(vdev = spdk_vhost_dev_find(req.ctrlr))) { + rc = -ENODEV; + goto invalid; + } + + rc = spdk_vhost_blk_destroy(vdev); + if (rc < 0) { + goto invalid; + } + + free_rpc_remove_vhost_blk_ctrlr(&req); + + if (id != NULL) { + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(conn, w); + } + + return; +invalid: + free_rpc_remove_vhost_blk_ctrlr(&req); + spdk_jsonrpc_send_error_response(conn, id, + SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); + +} +SPDK_RPC_REGISTER("remove_vhost_blk_controller", spdk_rpc_remove_vhost_blk_controller) + +static void +spdk_rpc_get_vhost_blk_controllers(struct spdk_jsonrpc_server_conn *conn, + const struct spdk_json_val *params, + const struct spdk_json_val *id) +{ + struct spdk_json_write_ctx *w; + struct spdk_vhost_dev *vdev = NULL; + struct spdk_bdev *bdev; + + if (params != NULL) { + spdk_jsonrpc_send_error_response(conn, id, + SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "get_vhost_block_controllers requires no parameters"); + return; + } + + if (id == NULL) { + return; + } + + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_array_begin(w); + while ((vdev = spdk_vhost_dev_next(vdev)) != NULL) { + if (vdev->type != SPDK_VHOST_DEV_T_BLK) + continue; + spdk_json_write_object_begin(w); + + spdk_json_write_name(w, "ctrlr"); + spdk_json_write_string(w, spdk_vhost_dev_get_name(vdev)); + + spdk_json_write_name(w, "cpu_mask"); + spdk_json_write_string_fmt(w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev)); + + bdev = spdk_vhost_blk_get_dev(vdev); + spdk_json_write_name(w, "bdev"); + if (bdev) + spdk_json_write_string(w, spdk_bdev_get_name(bdev)); + else + spdk_json_write_null(w); + + spdk_json_write_object_end(w); + } + spdk_json_write_array_end(w); + spdk_jsonrpc_end_result(conn, w); + + return; +} +SPDK_RPC_REGISTER("get_vhost_blk_controllers", spdk_rpc_get_vhost_blk_controllers) diff --git a/scripts/rpc.py b/scripts/rpc.py index e15f742eb..4962c824c 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -529,5 +529,34 @@ p.add_argument('ctrlr', help='controller name to remove device from') p.add_argument('scsi_dev_num', help='scsi_dev_num', type=int) p.set_defaults(func=remove_vhost_scsi_dev) +def construct_vhost_blk_controller(args): + params = { + 'ctrlr': args.ctrlr, + 'dev_name': args.dev_name, + } + if args.cpumask: + params['cpumask'] = args.cpumask + jsonrpc_call('construct_vhost_blk_controller', params) + +p = subparsers.add_parser('construct_vhost_blk_controller', help='Add a new vhost block controller') +p.add_argument('ctrlr', help='controller name') +p.add_argument('dev_name', help='device name') +p.add_argument('--cpumask', help='cpu mask for this controller') +p.set_defaults(func=construct_vhost_blk_controller) + +def remove_vhost_blk_controller(args): + params = {'ctrlr': args.ctrlr} + jsonrpc_call('remove_vhost_blk_controller', params) + +p = subparsers.add_parser('remove_vhost_blk_controller', help='Remove a vhost block controller') +p.add_argument('ctrlr', help='controller name') +p.set_defaults(func=remove_vhost_blk_controller) + +def get_vhost_blk_controllers(args): + print_dict(jsonrpc_call('get_vhost_blk_controllers')) + +p = subparsers.add_parser('get_vhost_blk_controllers', help='List vhost block controllers') +p.set_defaults(func=get_vhost_blk_controllers) + args = parser.parse_args() args.func(args)