Spdk/module/bdev/raid/bdev_raid_rpc.c
Seth Howell 07fe6a43d6 mk: move the bdev modules under module directory.
This is more accurate to what they are, and will make defining library
dependencies much simpler. This change in directory does not affect the
final placement of naming of libraries at the end of time.

Change-Id: Ic48a9233dff564e39ce357a9ea0a111ea2b6414b
Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465454
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-08-22 16:29:49 +00:00

423 lines
13 KiB
C

/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "spdk/rpc.h"
#include "spdk/bdev.h"
#include "bdev_raid.h"
#include "spdk/util.h"
#include "spdk/string.h"
#include "spdk_internal/log.h"
#include "spdk/env.h"
#define RPC_MAX_BASE_BDEVS 255
SPDK_LOG_REGISTER_COMPONENT("raidrpc", SPDK_LOG_RAID_RPC)
/*
* Input structure for get_raid_bdevs RPC
*/
struct rpc_get_raid_bdevs {
/* category - all or online or configuring or offline */
char *category;
};
/*
* brief:
* free_rpc_get_raids function frees RPC get_raids related parameters
* params:
* req - pointer to RPC request
* returns:
* none
*/
static void
free_rpc_get_raid_bdevs(struct rpc_get_raid_bdevs *req)
{
free(req->category);
}
/*
* Decoder object for RPC get_raids
*/
static const struct spdk_json_object_decoder rpc_get_raid_bdevs_decoders[] = {
{"category", offsetof(struct rpc_get_raid_bdevs, category), spdk_json_decode_string},
};
/*
* brief:
* spdk_rpc_get_raids function is the RPC for get_raids. This is used to list
* all the raid bdev names based on the input category requested. Category should be
* one of "all", "online", "configuring" or "offline". "all" means all the raids
* whether they are online or configuring or offline. "online" is the raid bdev which
* is registered with bdev layer. "configuring" is the raid bdev which does not have
* full configuration discovered yet. "offline" is the raid bdev which is not
* registered with bdev as of now and it has encountered any error or user has
* requested to offline the raid.
* params:
* requuest - pointer to json rpc request
* params - pointer to request parameters
* returns:
* none
*/
static void
spdk_rpc_get_raid_bdevs(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_get_raid_bdevs req = {};
struct spdk_json_write_ctx *w;
struct raid_bdev *raid_bdev;
if (spdk_json_decode_object(params, rpc_get_raid_bdevs_decoders,
SPDK_COUNTOF(rpc_get_raid_bdevs_decoders),
&req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
if (!(strcmp(req.category, "all") == 0 ||
strcmp(req.category, "online") == 0 ||
strcmp(req.category, "configuring") == 0 ||
strcmp(req.category, "offline") == 0)) {
spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL));
goto cleanup;
}
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_array_begin(w);
/* Get raid bdev list based on the category requested */
if (strcmp(req.category, "all") == 0) {
TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
spdk_json_write_string(w, raid_bdev->bdev.name);
}
} else if (strcmp(req.category, "online") == 0) {
TAILQ_FOREACH(raid_bdev, &g_raid_bdev_configured_list, state_link) {
spdk_json_write_string(w, raid_bdev->bdev.name);
}
} else if (strcmp(req.category, "configuring") == 0) {
TAILQ_FOREACH(raid_bdev, &g_raid_bdev_configuring_list, state_link) {
spdk_json_write_string(w, raid_bdev->bdev.name);
}
} else {
TAILQ_FOREACH(raid_bdev, &g_raid_bdev_offline_list, state_link) {
spdk_json_write_string(w, raid_bdev->bdev.name);
}
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(request, w);
cleanup:
free_rpc_get_raid_bdevs(&req);
}
SPDK_RPC_REGISTER("get_raid_bdevs", spdk_rpc_get_raid_bdevs, SPDK_RPC_RUNTIME)
/*
* Base bdevs in RPC construct_raid
*/
struct rpc_construct_raid_base_bdevs {
/* Number of base bdevs */
size_t num_base_bdevs;
/* List of base bdevs names */
char *base_bdevs[RPC_MAX_BASE_BDEVS];
};
/*
* Input structure for RPC construct_raid
*/
struct rpc_construct_raid_bdev {
/* Raid bdev name */
char *name;
/* RAID strip size KB, 'strip_size' is deprecated. */
uint32_t strip_size;
uint32_t strip_size_kb;
/* RAID raid level */
uint8_t raid_level;
/* Base bdevs information */
struct rpc_construct_raid_base_bdevs base_bdevs;
};
/*
* brief:
* free_rpc_construct_raid_bdev function is to free RPC construct_raid_bdev related parameters
* params:
* req - pointer to RPC request
* returns:
* none
*/
static void
free_rpc_construct_raid_bdev(struct rpc_construct_raid_bdev *req)
{
free(req->name);
for (size_t i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
free(req->base_bdevs.base_bdevs[i]);
}
}
/*
* Decoder function for RPC construct_raid_bdev to decode base bdevs list
*/
static int
decode_base_bdevs(const struct spdk_json_val *val, void *out)
{
struct rpc_construct_raid_base_bdevs *base_bdevs = out;
return spdk_json_decode_array(val, spdk_json_decode_string, base_bdevs->base_bdevs,
RPC_MAX_BASE_BDEVS, &base_bdevs->num_base_bdevs, sizeof(char *));
}
/*
* Decoder object for RPC construct_raid
*/
/* Note: strip_size is deprecated, one of the two options must be specified but not both. */
static const struct spdk_json_object_decoder rpc_construct_raid_bdev_decoders[] = {
{"name", offsetof(struct rpc_construct_raid_bdev, name), spdk_json_decode_string},
{"strip_size", offsetof(struct rpc_construct_raid_bdev, strip_size), spdk_json_decode_uint32, true},
{"strip_size_kb", offsetof(struct rpc_construct_raid_bdev, strip_size_kb), spdk_json_decode_uint32, true},
{"raid_level", offsetof(struct rpc_construct_raid_bdev, raid_level), spdk_json_decode_uint32},
{"base_bdevs", offsetof(struct rpc_construct_raid_bdev, base_bdevs), decode_base_bdevs},
};
/*
* brief:
* spdk_rpc_construct_raid_bdev function is the RPC for construct_raids. It takes
* input as raid bdev name, raid level, strip size in KB and list of base bdev names.
* params:
* requuest - pointer to json rpc request
* params - pointer to request parameters
* returns:
* none
*/
static void
spdk_rpc_construct_raid_bdev(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_construct_raid_bdev req = {};
struct spdk_json_write_ctx *w;
struct raid_bdev_config *raid_cfg;
int rc;
if (spdk_json_decode_object(params, rpc_construct_raid_bdev_decoders,
SPDK_COUNTOF(rpc_construct_raid_bdev_decoders),
&req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
if (req.strip_size == 0 && req.strip_size_kb == 0) {
spdk_jsonrpc_send_error_response(request, EINVAL, "strip size not specified");
goto cleanup;
} else if (req.strip_size > 0 && req.strip_size_kb > 0) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"please use only one strip size option");
goto cleanup;
} else if (req.strip_size > 0 && req.strip_size_kb == 0) {
SPDK_ERRLOG("the rpc param strip_size is deprecated.\n");
req.strip_size_kb = req.strip_size;
}
rc = raid_bdev_config_add(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs,
req.raid_level,
&raid_cfg);
if (rc != 0) {
spdk_jsonrpc_send_error_response_fmt(request, rc,
"Failed to add RAID bdev config %s: %s",
req.name, spdk_strerror(-rc));
goto cleanup;
}
for (size_t i = 0; i < req.base_bdevs.num_base_bdevs; i++) {
rc = raid_bdev_config_add_base_bdev(raid_cfg, req.base_bdevs.base_bdevs[i], i);
if (rc != 0) {
raid_bdev_config_cleanup(raid_cfg);
spdk_jsonrpc_send_error_response_fmt(request, rc,
"Failed to add base bdev %s to RAID bdev config %s: %s",
req.base_bdevs.base_bdevs[i], req.name,
spdk_strerror(-rc));
goto cleanup;
}
}
rc = raid_bdev_create(raid_cfg);
if (rc != 0) {
raid_bdev_config_cleanup(raid_cfg);
spdk_jsonrpc_send_error_response_fmt(request, rc,
"Failed to create RAID bdev %s: %s",
req.name, spdk_strerror(-rc));
goto cleanup;
}
rc = raid_bdev_add_base_devices(raid_cfg);
if (rc != 0) {
spdk_jsonrpc_send_error_response_fmt(request, rc,
"Failed to add any base bdev to RAID bdev %s: %s",
req.name, spdk_strerror(-rc));
goto cleanup;
}
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
cleanup:
free_rpc_construct_raid_bdev(&req);
}
SPDK_RPC_REGISTER("construct_raid_bdev", spdk_rpc_construct_raid_bdev, SPDK_RPC_RUNTIME)
/*
* Input structure for RPC destroy_raid
*/
struct rpc_destroy_raid_bdev {
/* raid bdev name */
char *name;
};
/*
* brief:
* free_rpc_destroy_raid_bdev function is used to free RPC destroy_raid_bdev related parameters
* params:
* req - pointer to RPC request
* params:
* none
*/
static void
free_rpc_destroy_raid_bdev(struct rpc_destroy_raid_bdev *req)
{
free(req->name);
}
/*
* Decoder object for RPC destroy_raid
*/
static const struct spdk_json_object_decoder rpc_destroy_raid_bdev_decoders[] = {
{"name", offsetof(struct rpc_destroy_raid_bdev, name), spdk_json_decode_string},
};
struct rpc_destroy_raid_bdev_ctx {
struct rpc_destroy_raid_bdev req;
struct raid_bdev_config *raid_cfg;
struct spdk_jsonrpc_request *request;
};
/*
* brief:
* params:
* cb_arg - pointer to the callback context.
* rc - return code of the destruction of the raid bdev.
* returns:
* none
*/
static void
destroy_raid_bdev_done(void *cb_arg, int rc)
{
struct rpc_destroy_raid_bdev_ctx *ctx = cb_arg;
struct raid_bdev_config *raid_cfg;
struct spdk_jsonrpc_request *request = ctx->request;
struct spdk_json_write_ctx *w;
if (rc != 0) {
SPDK_ERRLOG("Failed to destroy raid bdev %s (%d): %s\n",
ctx->req.name, rc, spdk_strerror(-rc));
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
spdk_strerror(-rc));
goto exit;
}
raid_cfg = ctx->raid_cfg;
assert(raid_cfg->raid_bdev == NULL);
raid_bdev_config_cleanup(raid_cfg);
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
exit:
free_rpc_destroy_raid_bdev(&ctx->req);
free(ctx);
}
/*
* brief:
* spdk_rpc_destroy_raid_bdev function is the RPC for destroy_raid. It takes raid
* name as input and destroy that raid bdev including freeing the base bdev
* resources.
* params:
* requuest - pointer to json rpc request
* params - pointer to request parameters
* returns:
* none
*/
static void
spdk_rpc_destroy_raid_bdev(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_destroy_raid_bdev_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
return;
}
if (spdk_json_decode_object(params, rpc_destroy_raid_bdev_decoders,
SPDK_COUNTOF(rpc_destroy_raid_bdev_decoders),
&ctx->req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
ctx->raid_cfg = raid_bdev_config_find_by_name(ctx->req.name);
if (ctx->raid_cfg == NULL) {
spdk_jsonrpc_send_error_response_fmt(request, ENODEV,
"raid bdev %s is not found in config",
ctx->req.name);
goto cleanup;
}
ctx->request = request;
/* Remove all the base bdevs from this raid bdev before destroying the raid bdev */
raid_bdev_remove_base_devices(ctx->raid_cfg, destroy_raid_bdev_done, ctx);
return;
cleanup:
free_rpc_destroy_raid_bdev(&ctx->req);
free(ctx);
}
SPDK_RPC_REGISTER("destroy_raid_bdev", spdk_rpc_destroy_raid_bdev, SPDK_RPC_RUNTIME)