1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2018 Intel Corporation. 307fe6a43SSeth Howell * All rights reserved. 407fe6a43SSeth Howell */ 507fe6a43SSeth Howell 607fe6a43SSeth Howell #include "spdk/rpc.h" 707fe6a43SSeth Howell #include "spdk/bdev.h" 807fe6a43SSeth Howell #include "bdev_raid.h" 907fe6a43SSeth Howell #include "spdk/util.h" 1007fe6a43SSeth Howell #include "spdk/string.h" 114e8e97c8STomasz Zawadzki #include "spdk/log.h" 1207fe6a43SSeth Howell #include "spdk/env.h" 1307fe6a43SSeth Howell 1407fe6a43SSeth Howell #define RPC_MAX_BASE_BDEVS 255 1507fe6a43SSeth Howell 1607fe6a43SSeth Howell /* 17b9477173SMaciej Wawryk * Input structure for bdev_raid_get_bdevs RPC 1807fe6a43SSeth Howell */ 19b9477173SMaciej Wawryk struct rpc_bdev_raid_get_bdevs { 2007fe6a43SSeth Howell /* category - all or online or configuring or offline */ 2107fe6a43SSeth Howell char *category; 2207fe6a43SSeth Howell }; 2307fe6a43SSeth Howell 2407fe6a43SSeth Howell /* 2507fe6a43SSeth Howell * brief: 26b9477173SMaciej Wawryk * free_rpc_bdev_raid_get_bdevs function frees RPC bdev_raid_get_bdevs related parameters 2707fe6a43SSeth Howell * params: 2807fe6a43SSeth Howell * req - pointer to RPC request 2907fe6a43SSeth Howell * returns: 3007fe6a43SSeth Howell * none 3107fe6a43SSeth Howell */ 3207fe6a43SSeth Howell static void 33b9477173SMaciej Wawryk free_rpc_bdev_raid_get_bdevs(struct rpc_bdev_raid_get_bdevs *req) 3407fe6a43SSeth Howell { 3507fe6a43SSeth Howell free(req->category); 3607fe6a43SSeth Howell } 3707fe6a43SSeth Howell 3807fe6a43SSeth Howell /* 3907fe6a43SSeth Howell * Decoder object for RPC get_raids 4007fe6a43SSeth Howell */ 41b9477173SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_raid_get_bdevs_decoders[] = { 42b9477173SMaciej Wawryk {"category", offsetof(struct rpc_bdev_raid_get_bdevs, category), spdk_json_decode_string}, 4307fe6a43SSeth Howell }; 4407fe6a43SSeth Howell 4507fe6a43SSeth Howell /* 4607fe6a43SSeth Howell * brief: 47fe5ba303SSeth Howell * rpc_bdev_raid_get_bdevs function is the RPC for rpc_bdev_raid_get_bdevs. This is used to list 4807fe6a43SSeth Howell * all the raid bdev names based on the input category requested. Category should be 4907fe6a43SSeth Howell * one of "all", "online", "configuring" or "offline". "all" means all the raids 5007fe6a43SSeth Howell * whether they are online or configuring or offline. "online" is the raid bdev which 5107fe6a43SSeth Howell * is registered with bdev layer. "configuring" is the raid bdev which does not have 5207fe6a43SSeth Howell * full configuration discovered yet. "offline" is the raid bdev which is not 5307fe6a43SSeth Howell * registered with bdev as of now and it has encountered any error or user has 5407fe6a43SSeth Howell * requested to offline the raid. 5507fe6a43SSeth Howell * params: 5617f7cf9bSpaul luse * request - pointer to json rpc request 5707fe6a43SSeth Howell * params - pointer to request parameters 5807fe6a43SSeth Howell * returns: 5907fe6a43SSeth Howell * none 6007fe6a43SSeth Howell */ 6107fe6a43SSeth Howell static void 62fe5ba303SSeth Howell rpc_bdev_raid_get_bdevs(struct spdk_jsonrpc_request *request, 6307fe6a43SSeth Howell const struct spdk_json_val *params) 6407fe6a43SSeth Howell { 65b9477173SMaciej Wawryk struct rpc_bdev_raid_get_bdevs req = {}; 6607fe6a43SSeth Howell struct spdk_json_write_ctx *w; 6707fe6a43SSeth Howell struct raid_bdev *raid_bdev; 6846ff15a6SArtur Paszkiewicz enum raid_bdev_state state; 6907fe6a43SSeth Howell 70b9477173SMaciej Wawryk if (spdk_json_decode_object(params, rpc_bdev_raid_get_bdevs_decoders, 71b9477173SMaciej Wawryk SPDK_COUNTOF(rpc_bdev_raid_get_bdevs_decoders), 7207fe6a43SSeth Howell &req)) { 7331710892SArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 7407fe6a43SSeth Howell "spdk_json_decode_object failed"); 7507fe6a43SSeth Howell goto cleanup; 7607fe6a43SSeth Howell } 7707fe6a43SSeth Howell 7846ff15a6SArtur Paszkiewicz state = raid_bdev_str_to_state(req.category); 7946ff15a6SArtur Paszkiewicz if (state == RAID_BDEV_STATE_MAX && strcmp(req.category, "all") != 0) { 8007fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL)); 8107fe6a43SSeth Howell goto cleanup; 8207fe6a43SSeth Howell } 8307fe6a43SSeth Howell 8407fe6a43SSeth Howell w = spdk_jsonrpc_begin_result(request); 8507fe6a43SSeth Howell spdk_json_write_array_begin(w); 8607fe6a43SSeth Howell 8707fe6a43SSeth Howell /* Get raid bdev list based on the category requested */ 8807fe6a43SSeth Howell TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) { 8946ff15a6SArtur Paszkiewicz if (raid_bdev->state == state || state == RAID_BDEV_STATE_MAX) { 908a6bb6a8SArtur Paszkiewicz char uuid_str[SPDK_UUID_STRING_LEN]; 918a6bb6a8SArtur Paszkiewicz 92ec6d94b6SArtur Paszkiewicz spdk_json_write_object_begin(w); 93ec6d94b6SArtur Paszkiewicz spdk_json_write_named_string(w, "name", raid_bdev->bdev.name); 948a6bb6a8SArtur Paszkiewicz spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &raid_bdev->bdev.uuid); 958a6bb6a8SArtur Paszkiewicz spdk_json_write_named_string(w, "uuid", uuid_str); 96ec6d94b6SArtur Paszkiewicz raid_bdev_write_info_json(raid_bdev, w); 97ec6d94b6SArtur Paszkiewicz spdk_json_write_object_end(w); 9807fe6a43SSeth Howell } 9907fe6a43SSeth Howell } 10007fe6a43SSeth Howell spdk_json_write_array_end(w); 10107fe6a43SSeth Howell spdk_jsonrpc_end_result(request, w); 10207fe6a43SSeth Howell 10307fe6a43SSeth Howell cleanup: 104b9477173SMaciej Wawryk free_rpc_bdev_raid_get_bdevs(&req); 10507fe6a43SSeth Howell } 106fe5ba303SSeth Howell SPDK_RPC_REGISTER("bdev_raid_get_bdevs", rpc_bdev_raid_get_bdevs, SPDK_RPC_RUNTIME) 10707fe6a43SSeth Howell 10807fe6a43SSeth Howell /* 109f0731534SMaciej Wawryk * Base bdevs in RPC bdev_raid_create 11007fe6a43SSeth Howell */ 111f0731534SMaciej Wawryk struct rpc_bdev_raid_create_base_bdevs { 11207fe6a43SSeth Howell /* Number of base bdevs */ 11307fe6a43SSeth Howell size_t num_base_bdevs; 11407fe6a43SSeth Howell 11507fe6a43SSeth Howell /* List of base bdevs names */ 11607fe6a43SSeth Howell char *base_bdevs[RPC_MAX_BASE_BDEVS]; 11707fe6a43SSeth Howell }; 11807fe6a43SSeth Howell 11907fe6a43SSeth Howell /* 120f0731534SMaciej Wawryk * Input structure for RPC rpc_bdev_raid_create 12107fe6a43SSeth Howell */ 122f0731534SMaciej Wawryk struct rpc_bdev_raid_create { 12307fe6a43SSeth Howell /* Raid bdev name */ 12407fe6a43SSeth Howell char *name; 12507fe6a43SSeth Howell 12630d83eb6Spaul luse /* RAID strip size in KB */ 12707fe6a43SSeth Howell uint32_t strip_size_kb; 12807fe6a43SSeth Howell 12907fe6a43SSeth Howell /* RAID raid level */ 130445e667fSArtur Paszkiewicz enum raid_level level; 13107fe6a43SSeth Howell 13207fe6a43SSeth Howell /* Base bdevs information */ 133f0731534SMaciej Wawryk struct rpc_bdev_raid_create_base_bdevs base_bdevs; 1341db41324SKrzysztof Karas 1351db41324SKrzysztof Karas /* UUID for this raid bdev */ 136e85f1f11SKonrad Sztyber struct spdk_uuid uuid; 137e39760fdSKrzysztof Smolinski 138e39760fdSKrzysztof Smolinski /* If set, information about raid bdev will be stored in superblock on each base bdev */ 139e39760fdSKrzysztof Smolinski bool superblock_enabled; 14007fe6a43SSeth Howell }; 14107fe6a43SSeth Howell 14207fe6a43SSeth Howell /* 143445e667fSArtur Paszkiewicz * Decoder function for RPC bdev_raid_create to decode raid level 144445e667fSArtur Paszkiewicz */ 145445e667fSArtur Paszkiewicz static int 146445e667fSArtur Paszkiewicz decode_raid_level(const struct spdk_json_val *val, void *out) 147445e667fSArtur Paszkiewicz { 148445e667fSArtur Paszkiewicz int ret; 149445e667fSArtur Paszkiewicz char *str = NULL; 150445e667fSArtur Paszkiewicz enum raid_level level; 151445e667fSArtur Paszkiewicz 152445e667fSArtur Paszkiewicz ret = spdk_json_decode_string(val, &str); 153a2606d4bSMaciej Szwed if (ret == 0 && str != NULL) { 15446ff15a6SArtur Paszkiewicz level = raid_bdev_str_to_level(str); 155445e667fSArtur Paszkiewicz if (level == INVALID_RAID_LEVEL) { 156445e667fSArtur Paszkiewicz ret = -EINVAL; 157445e667fSArtur Paszkiewicz } else { 158445e667fSArtur Paszkiewicz *(enum raid_level *)out = level; 159445e667fSArtur Paszkiewicz } 160445e667fSArtur Paszkiewicz } 161445e667fSArtur Paszkiewicz 162445e667fSArtur Paszkiewicz free(str); 163445e667fSArtur Paszkiewicz return ret; 164445e667fSArtur Paszkiewicz } 165445e667fSArtur Paszkiewicz 166445e667fSArtur Paszkiewicz /* 167f0731534SMaciej Wawryk * Decoder function for RPC bdev_raid_create to decode base bdevs list 16807fe6a43SSeth Howell */ 16907fe6a43SSeth Howell static int 17007fe6a43SSeth Howell decode_base_bdevs(const struct spdk_json_val *val, void *out) 17107fe6a43SSeth Howell { 172f0731534SMaciej Wawryk struct rpc_bdev_raid_create_base_bdevs *base_bdevs = out; 17307fe6a43SSeth Howell return spdk_json_decode_array(val, spdk_json_decode_string, base_bdevs->base_bdevs, 17407fe6a43SSeth Howell RPC_MAX_BASE_BDEVS, &base_bdevs->num_base_bdevs, sizeof(char *)); 17507fe6a43SSeth Howell } 17607fe6a43SSeth Howell 17707fe6a43SSeth Howell /* 178f0731534SMaciej Wawryk * Decoder object for RPC bdev_raid_create 17907fe6a43SSeth Howell */ 180f0731534SMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_raid_create_decoders[] = { 181f0731534SMaciej Wawryk {"name", offsetof(struct rpc_bdev_raid_create, name), spdk_json_decode_string}, 182f0731534SMaciej Wawryk {"strip_size_kb", offsetof(struct rpc_bdev_raid_create, strip_size_kb), spdk_json_decode_uint32, true}, 183445e667fSArtur Paszkiewicz {"raid_level", offsetof(struct rpc_bdev_raid_create, level), decode_raid_level}, 184f0731534SMaciej Wawryk {"base_bdevs", offsetof(struct rpc_bdev_raid_create, base_bdevs), decode_base_bdevs}, 185e85f1f11SKonrad Sztyber {"uuid", offsetof(struct rpc_bdev_raid_create, uuid), spdk_json_decode_uuid, true}, 186e39760fdSKrzysztof Smolinski {"superblock", offsetof(struct rpc_bdev_raid_create, superblock_enabled), spdk_json_decode_bool, true}, 18707fe6a43SSeth Howell }; 18807fe6a43SSeth Howell 1896eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create_ctx { 1906eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create req; 1916eed119eSArtur Paszkiewicz struct raid_bdev *raid_bdev; 1926eed119eSArtur Paszkiewicz struct spdk_jsonrpc_request *request; 1936eed119eSArtur Paszkiewicz uint8_t remaining; 1946eed119eSArtur Paszkiewicz int status; 1956eed119eSArtur Paszkiewicz }; 1966eed119eSArtur Paszkiewicz 1976eed119eSArtur Paszkiewicz static void 1986eed119eSArtur Paszkiewicz free_rpc_bdev_raid_create_ctx(struct rpc_bdev_raid_create_ctx *ctx) 1996eed119eSArtur Paszkiewicz { 2006eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create *req; 2016eed119eSArtur Paszkiewicz size_t i; 2026eed119eSArtur Paszkiewicz 2036eed119eSArtur Paszkiewicz if (!ctx) { 2046eed119eSArtur Paszkiewicz return; 2056eed119eSArtur Paszkiewicz } 2066eed119eSArtur Paszkiewicz 2076eed119eSArtur Paszkiewicz req = &ctx->req; 2086eed119eSArtur Paszkiewicz 2096eed119eSArtur Paszkiewicz free(req->name); 2106eed119eSArtur Paszkiewicz for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) { 2116eed119eSArtur Paszkiewicz free(req->base_bdevs.base_bdevs[i]); 2126eed119eSArtur Paszkiewicz } 2136eed119eSArtur Paszkiewicz 2146eed119eSArtur Paszkiewicz free(ctx); 2156eed119eSArtur Paszkiewicz } 2166eed119eSArtur Paszkiewicz 2176eed119eSArtur Paszkiewicz static void 2186eed119eSArtur Paszkiewicz rpc_bdev_raid_create_add_base_bdev_cb(void *_ctx, int status) 2196eed119eSArtur Paszkiewicz { 2206eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create_ctx *ctx = _ctx; 2216eed119eSArtur Paszkiewicz 2226eed119eSArtur Paszkiewicz if (status != 0) { 2236eed119eSArtur Paszkiewicz ctx->status = status; 2246eed119eSArtur Paszkiewicz } 2256eed119eSArtur Paszkiewicz 2266eed119eSArtur Paszkiewicz assert(ctx->remaining != 0); 2276eed119eSArtur Paszkiewicz if (--ctx->remaining > 0) { 2286eed119eSArtur Paszkiewicz return; 2296eed119eSArtur Paszkiewicz } 2306eed119eSArtur Paszkiewicz 2316eed119eSArtur Paszkiewicz if (ctx->status != 0) { 2326eed119eSArtur Paszkiewicz raid_bdev_delete(ctx->raid_bdev, NULL, NULL); 2336eed119eSArtur Paszkiewicz spdk_jsonrpc_send_error_response_fmt(ctx->request, ctx->status, 2346eed119eSArtur Paszkiewicz "Failed to create RAID bdev %s: %s", 2356eed119eSArtur Paszkiewicz ctx->req.name, 2366eed119eSArtur Paszkiewicz spdk_strerror(-ctx->status)); 2376eed119eSArtur Paszkiewicz } else { 2386eed119eSArtur Paszkiewicz spdk_jsonrpc_send_bool_response(ctx->request, true); 2396eed119eSArtur Paszkiewicz } 2406eed119eSArtur Paszkiewicz 2416eed119eSArtur Paszkiewicz free_rpc_bdev_raid_create_ctx(ctx); 2426eed119eSArtur Paszkiewicz } 2436eed119eSArtur Paszkiewicz 24407fe6a43SSeth Howell /* 24507fe6a43SSeth Howell * brief: 246fe5ba303SSeth Howell * rpc_bdev_raid_create function is the RPC for creating RAID bdevs. It takes 24707fe6a43SSeth Howell * input as raid bdev name, raid level, strip size in KB and list of base bdev names. 24807fe6a43SSeth Howell * params: 24917f7cf9bSpaul luse * request - pointer to json rpc request 25007fe6a43SSeth Howell * params - pointer to request parameters 25107fe6a43SSeth Howell * returns: 25207fe6a43SSeth Howell * none 25307fe6a43SSeth Howell */ 25407fe6a43SSeth Howell static void 255fe5ba303SSeth Howell rpc_bdev_raid_create(struct spdk_jsonrpc_request *request, 25607fe6a43SSeth Howell const struct spdk_json_val *params) 25707fe6a43SSeth Howell { 2586eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create *req; 259dccdd1e5SArtur Paszkiewicz struct raid_bdev *raid_bdev; 26007fe6a43SSeth Howell int rc; 2619d94e1f5SArtur Paszkiewicz size_t i; 2626eed119eSArtur Paszkiewicz struct rpc_bdev_raid_create_ctx *ctx; 2636eed119eSArtur Paszkiewicz uint8_t num_base_bdevs; 2646eed119eSArtur Paszkiewicz 2656eed119eSArtur Paszkiewicz ctx = calloc(1, sizeof(*ctx)); 2666eed119eSArtur Paszkiewicz if (ctx == NULL) { 2676eed119eSArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2686eed119eSArtur Paszkiewicz goto cleanup; 2696eed119eSArtur Paszkiewicz } 2706eed119eSArtur Paszkiewicz req = &ctx->req; 27107fe6a43SSeth Howell 272f0731534SMaciej Wawryk if (spdk_json_decode_object(params, rpc_bdev_raid_create_decoders, 273f0731534SMaciej Wawryk SPDK_COUNTOF(rpc_bdev_raid_create_decoders), 2746eed119eSArtur Paszkiewicz req)) { 27531710892SArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 27607fe6a43SSeth Howell "spdk_json_decode_object failed"); 27707fe6a43SSeth Howell goto cleanup; 27807fe6a43SSeth Howell } 2796eed119eSArtur Paszkiewicz num_base_bdevs = req->base_bdevs.num_base_bdevs; 28007fe6a43SSeth Howell 281c00eb482SYankun Li for (i = 0; i < num_base_bdevs; i++) { 282c00eb482SYankun Li if (strlen(req->base_bdevs.base_bdevs[i]) == 0) { 283c00eb482SYankun Li spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 284c00eb482SYankun Li "The base bdev name cannot be empty: %s", 285c00eb482SYankun Li spdk_strerror(EINVAL)); 286c00eb482SYankun Li goto cleanup; 287c00eb482SYankun Li } 288c00eb482SYankun Li } 289c00eb482SYankun Li 2906eed119eSArtur Paszkiewicz rc = raid_bdev_create(req->name, req->strip_size_kb, num_base_bdevs, 2916eed119eSArtur Paszkiewicz req->level, req->superblock_enabled, &req->uuid, &raid_bdev); 29207fe6a43SSeth Howell if (rc != 0) { 29307fe6a43SSeth Howell spdk_jsonrpc_send_error_response_fmt(request, rc, 29407fe6a43SSeth Howell "Failed to create RAID bdev %s: %s", 2956eed119eSArtur Paszkiewicz req->name, spdk_strerror(-rc)); 29607fe6a43SSeth Howell goto cleanup; 29707fe6a43SSeth Howell } 29807fe6a43SSeth Howell 2996eed119eSArtur Paszkiewicz ctx->raid_bdev = raid_bdev; 3006eed119eSArtur Paszkiewicz ctx->request = request; 3016eed119eSArtur Paszkiewicz ctx->remaining = num_base_bdevs; 302dccdd1e5SArtur Paszkiewicz 3036eed119eSArtur Paszkiewicz assert(num_base_bdevs > 0); 3046eed119eSArtur Paszkiewicz 3056eed119eSArtur Paszkiewicz for (i = 0; i < num_base_bdevs; i++) { 3066eed119eSArtur Paszkiewicz const char *base_bdev_name = req->base_bdevs.base_bdevs[i]; 3076eed119eSArtur Paszkiewicz 308e9af23deSArtur Paszkiewicz rc = raid_bdev_add_base_bdev(raid_bdev, base_bdev_name, 3096eed119eSArtur Paszkiewicz rpc_bdev_raid_create_add_base_bdev_cb, ctx); 310dccdd1e5SArtur Paszkiewicz if (rc == -ENODEV) { 311dccdd1e5SArtur Paszkiewicz SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); 3126eed119eSArtur Paszkiewicz assert(ctx->remaining > 1 || i + 1 == num_base_bdevs); 3136eed119eSArtur Paszkiewicz rpc_bdev_raid_create_add_base_bdev_cb(ctx, 0); 314dccdd1e5SArtur Paszkiewicz } else if (rc != 0) { 3156eed119eSArtur Paszkiewicz SPDK_DEBUGLOG(bdev_raid, "Failed to add base bdev %s to RAID bdev %s: %s", 3166eed119eSArtur Paszkiewicz base_bdev_name, req->name, spdk_strerror(-rc)); 3176eed119eSArtur Paszkiewicz ctx->remaining -= (num_base_bdevs - i - 1); 3186eed119eSArtur Paszkiewicz rpc_bdev_raid_create_add_base_bdev_cb(ctx, rc); 3196eed119eSArtur Paszkiewicz break; 32007fe6a43SSeth Howell } 321dccdd1e5SArtur Paszkiewicz } 3226eed119eSArtur Paszkiewicz return; 32307fe6a43SSeth Howell cleanup: 3246eed119eSArtur Paszkiewicz free_rpc_bdev_raid_create_ctx(ctx); 32507fe6a43SSeth Howell } 326fe5ba303SSeth Howell SPDK_RPC_REGISTER("bdev_raid_create", rpc_bdev_raid_create, SPDK_RPC_RUNTIME) 32707fe6a43SSeth Howell 32807fe6a43SSeth Howell /* 32927d8ca2cSMaciej Wawryk * Input structure for RPC deleting a raid bdev 33007fe6a43SSeth Howell */ 33127d8ca2cSMaciej Wawryk struct rpc_bdev_raid_delete { 33207fe6a43SSeth Howell /* raid bdev name */ 33307fe6a43SSeth Howell char *name; 33407fe6a43SSeth Howell }; 33507fe6a43SSeth Howell 33607fe6a43SSeth Howell /* 33707fe6a43SSeth Howell * brief: 33827d8ca2cSMaciej Wawryk * free_rpc_bdev_raid_delete function is used to free RPC bdev_raid_delete related parameters 33907fe6a43SSeth Howell * params: 34007fe6a43SSeth Howell * req - pointer to RPC request 34107fe6a43SSeth Howell * params: 34207fe6a43SSeth Howell * none 34307fe6a43SSeth Howell */ 34407fe6a43SSeth Howell static void 34527d8ca2cSMaciej Wawryk free_rpc_bdev_raid_delete(struct rpc_bdev_raid_delete *req) 34607fe6a43SSeth Howell { 34707fe6a43SSeth Howell free(req->name); 34807fe6a43SSeth Howell } 34907fe6a43SSeth Howell 35007fe6a43SSeth Howell /* 35127d8ca2cSMaciej Wawryk * Decoder object for RPC raid_bdev_delete 35207fe6a43SSeth Howell */ 35327d8ca2cSMaciej Wawryk static const struct spdk_json_object_decoder rpc_bdev_raid_delete_decoders[] = { 35427d8ca2cSMaciej Wawryk {"name", offsetof(struct rpc_bdev_raid_delete, name), spdk_json_decode_string}, 35507fe6a43SSeth Howell }; 35607fe6a43SSeth Howell 35727d8ca2cSMaciej Wawryk struct rpc_bdev_raid_delete_ctx { 35827d8ca2cSMaciej Wawryk struct rpc_bdev_raid_delete req; 35907fe6a43SSeth Howell struct spdk_jsonrpc_request *request; 36007fe6a43SSeth Howell }; 36107fe6a43SSeth Howell 36207fe6a43SSeth Howell /* 36307fe6a43SSeth Howell * brief: 36407fe6a43SSeth Howell * params: 36507fe6a43SSeth Howell * cb_arg - pointer to the callback context. 36627d8ca2cSMaciej Wawryk * rc - return code of the deletion of the raid bdev. 36707fe6a43SSeth Howell * returns: 36807fe6a43SSeth Howell * none 36907fe6a43SSeth Howell */ 37007fe6a43SSeth Howell static void 37127d8ca2cSMaciej Wawryk bdev_raid_delete_done(void *cb_arg, int rc) 37207fe6a43SSeth Howell { 37327d8ca2cSMaciej Wawryk struct rpc_bdev_raid_delete_ctx *ctx = cb_arg; 37407fe6a43SSeth Howell struct spdk_jsonrpc_request *request = ctx->request; 37507fe6a43SSeth Howell 37607fe6a43SSeth Howell if (rc != 0) { 37727d8ca2cSMaciej Wawryk SPDK_ERRLOG("Failed to delete raid bdev %s (%d): %s\n", 37807fe6a43SSeth Howell ctx->req.name, rc, spdk_strerror(-rc)); 37907fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 38007fe6a43SSeth Howell spdk_strerror(-rc)); 38107fe6a43SSeth Howell goto exit; 38207fe6a43SSeth Howell } 38307fe6a43SSeth Howell 384d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 38507fe6a43SSeth Howell exit: 38627d8ca2cSMaciej Wawryk free_rpc_bdev_raid_delete(&ctx->req); 38707fe6a43SSeth Howell free(ctx); 38807fe6a43SSeth Howell } 38907fe6a43SSeth Howell 39007fe6a43SSeth Howell /* 39107fe6a43SSeth Howell * brief: 392fe5ba303SSeth Howell * rpc_bdev_raid_delete function is the RPC for deleting a raid bdev. It takes raid 39327d8ca2cSMaciej Wawryk * name as input and delete that raid bdev including freeing the base bdev 39407fe6a43SSeth Howell * resources. 39507fe6a43SSeth Howell * params: 39617f7cf9bSpaul luse * request - pointer to json rpc request 39707fe6a43SSeth Howell * params - pointer to request parameters 39807fe6a43SSeth Howell * returns: 39907fe6a43SSeth Howell * none 40007fe6a43SSeth Howell */ 40107fe6a43SSeth Howell static void 402fe5ba303SSeth Howell rpc_bdev_raid_delete(struct spdk_jsonrpc_request *request, 40307fe6a43SSeth Howell const struct spdk_json_val *params) 40407fe6a43SSeth Howell { 40527d8ca2cSMaciej Wawryk struct rpc_bdev_raid_delete_ctx *ctx; 406dccdd1e5SArtur Paszkiewicz struct raid_bdev *raid_bdev; 40707fe6a43SSeth Howell 40807fe6a43SSeth Howell ctx = calloc(1, sizeof(*ctx)); 40907fe6a43SSeth Howell if (!ctx) { 41007fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 41107fe6a43SSeth Howell return; 41207fe6a43SSeth Howell } 41307fe6a43SSeth Howell 41427d8ca2cSMaciej Wawryk if (spdk_json_decode_object(params, rpc_bdev_raid_delete_decoders, 41527d8ca2cSMaciej Wawryk SPDK_COUNTOF(rpc_bdev_raid_delete_decoders), 41607fe6a43SSeth Howell &ctx->req)) { 41731710892SArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 41807fe6a43SSeth Howell "spdk_json_decode_object failed"); 41907fe6a43SSeth Howell goto cleanup; 42007fe6a43SSeth Howell } 42107fe6a43SSeth Howell 422dccdd1e5SArtur Paszkiewicz raid_bdev = raid_bdev_find_by_name(ctx->req.name); 423dccdd1e5SArtur Paszkiewicz if (raid_bdev == NULL) { 42431710892SArtur Paszkiewicz spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, 425dccdd1e5SArtur Paszkiewicz "raid bdev %s not found", 42607fe6a43SSeth Howell ctx->req.name); 42707fe6a43SSeth Howell goto cleanup; 42807fe6a43SSeth Howell } 42907fe6a43SSeth Howell 43007fe6a43SSeth Howell ctx->request = request; 43107fe6a43SSeth Howell 432dccdd1e5SArtur Paszkiewicz raid_bdev_delete(raid_bdev, bdev_raid_delete_done, ctx); 43307fe6a43SSeth Howell 43407fe6a43SSeth Howell return; 43507fe6a43SSeth Howell 43607fe6a43SSeth Howell cleanup: 43727d8ca2cSMaciej Wawryk free_rpc_bdev_raid_delete(&ctx->req); 43807fe6a43SSeth Howell free(ctx); 43907fe6a43SSeth Howell } 440fe5ba303SSeth Howell SPDK_RPC_REGISTER("bdev_raid_delete", rpc_bdev_raid_delete, SPDK_RPC_RUNTIME) 44123850b03SKrzysztof Smolinski 44223850b03SKrzysztof Smolinski /* 443524129a9SKrzysztof Smolinski * Base bdevs in RPC bdev_raid_add_base_bdev 444524129a9SKrzysztof Smolinski */ 445524129a9SKrzysztof Smolinski struct rpc_bdev_raid_add_base_bdev { 446524129a9SKrzysztof Smolinski /* Base bdev name */ 447524129a9SKrzysztof Smolinski char *base_bdev; 448524129a9SKrzysztof Smolinski 449524129a9SKrzysztof Smolinski /* Raid bdev name */ 450524129a9SKrzysztof Smolinski char *raid_bdev; 451524129a9SKrzysztof Smolinski }; 452524129a9SKrzysztof Smolinski 453524129a9SKrzysztof Smolinski /* 454524129a9SKrzysztof Smolinski * brief: 455524129a9SKrzysztof Smolinski * free_rpc_bdev_raid_add_base_bdev function is to free RPC 456524129a9SKrzysztof Smolinski * bdev_raid_add_base_bdev related parameters. 457524129a9SKrzysztof Smolinski * params: 458524129a9SKrzysztof Smolinski * req - pointer to RPC request 459524129a9SKrzysztof Smolinski * returns: 460524129a9SKrzysztof Smolinski * none 461524129a9SKrzysztof Smolinski */ 462524129a9SKrzysztof Smolinski static void 463524129a9SKrzysztof Smolinski free_rpc_bdev_raid_add_base_bdev(struct rpc_bdev_raid_add_base_bdev *req) 464524129a9SKrzysztof Smolinski { 465524129a9SKrzysztof Smolinski free(req->base_bdev); 466524129a9SKrzysztof Smolinski free(req->raid_bdev); 467524129a9SKrzysztof Smolinski } 468524129a9SKrzysztof Smolinski 469524129a9SKrzysztof Smolinski /* 470524129a9SKrzysztof Smolinski * Decoder object for RPC bdev_raid_add_base_bdev 471524129a9SKrzysztof Smolinski */ 472524129a9SKrzysztof Smolinski static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { 473524129a9SKrzysztof Smolinski {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev), spdk_json_decode_string}, 474524129a9SKrzysztof Smolinski {"raid_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, raid_bdev), spdk_json_decode_string}, 475524129a9SKrzysztof Smolinski }; 476524129a9SKrzysztof Smolinski 477524129a9SKrzysztof Smolinski static void 478524129a9SKrzysztof Smolinski rpc_bdev_raid_add_base_bdev_done(void *ctx, int status) 479524129a9SKrzysztof Smolinski { 480524129a9SKrzysztof Smolinski struct spdk_jsonrpc_request *request = ctx; 481524129a9SKrzysztof Smolinski 482524129a9SKrzysztof Smolinski if (status != 0) { 483524129a9SKrzysztof Smolinski spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to add base bdev to RAID bdev: %s", 484524129a9SKrzysztof Smolinski spdk_strerror(-status)); 485524129a9SKrzysztof Smolinski return; 486524129a9SKrzysztof Smolinski } 487524129a9SKrzysztof Smolinski 488524129a9SKrzysztof Smolinski spdk_jsonrpc_send_bool_response(request, true); 489524129a9SKrzysztof Smolinski } 490524129a9SKrzysztof Smolinski 491524129a9SKrzysztof Smolinski static void 492524129a9SKrzysztof Smolinski rpc_bdev_raid_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 493524129a9SKrzysztof Smolinski { 494524129a9SKrzysztof Smolinski } 495524129a9SKrzysztof Smolinski 496524129a9SKrzysztof Smolinski /* 497524129a9SKrzysztof Smolinski * brief: 498524129a9SKrzysztof Smolinski * bdev_raid_add_base_bdev function is the RPC for adding base bdev to a raid bdev. 499524129a9SKrzysztof Smolinski * It takes base bdev and raid bdev names as input. 500524129a9SKrzysztof Smolinski * params: 501524129a9SKrzysztof Smolinski * request - pointer to json rpc request 502524129a9SKrzysztof Smolinski * params - pointer to request parameters 503524129a9SKrzysztof Smolinski * returns: 504524129a9SKrzysztof Smolinski * none 505524129a9SKrzysztof Smolinski */ 506524129a9SKrzysztof Smolinski static void 507524129a9SKrzysztof Smolinski rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, 508524129a9SKrzysztof Smolinski const struct spdk_json_val *params) 509524129a9SKrzysztof Smolinski { 510524129a9SKrzysztof Smolinski struct rpc_bdev_raid_add_base_bdev req = {}; 511524129a9SKrzysztof Smolinski struct raid_bdev *raid_bdev; 512524129a9SKrzysztof Smolinski int rc; 513524129a9SKrzysztof Smolinski 514524129a9SKrzysztof Smolinski if (spdk_json_decode_object(params, rpc_bdev_raid_add_base_bdev_decoders, 515524129a9SKrzysztof Smolinski SPDK_COUNTOF(rpc_bdev_raid_add_base_bdev_decoders), 516524129a9SKrzysztof Smolinski &req)) { 517524129a9SKrzysztof Smolinski spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 518524129a9SKrzysztof Smolinski "spdk_json_decode_object failed"); 519524129a9SKrzysztof Smolinski goto cleanup; 520524129a9SKrzysztof Smolinski } 521524129a9SKrzysztof Smolinski 522524129a9SKrzysztof Smolinski raid_bdev = raid_bdev_find_by_name(req.raid_bdev); 523524129a9SKrzysztof Smolinski if (raid_bdev == NULL) { 524524129a9SKrzysztof Smolinski spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "raid bdev %s is not found in config", 525524129a9SKrzysztof Smolinski req.raid_bdev); 526524129a9SKrzysztof Smolinski goto cleanup; 527524129a9SKrzysztof Smolinski } 528524129a9SKrzysztof Smolinski 529e9af23deSArtur Paszkiewicz rc = raid_bdev_add_base_bdev(raid_bdev, req.base_bdev, rpc_bdev_raid_add_base_bdev_done, request); 530524129a9SKrzysztof Smolinski if (rc != 0) { 531524129a9SKrzysztof Smolinski spdk_jsonrpc_send_error_response_fmt(request, rc, 5320074299dSArtur Paszkiewicz "Failed to add base bdev %s to RAID bdev %s: %s", 533524129a9SKrzysztof Smolinski req.base_bdev, req.raid_bdev, 534524129a9SKrzysztof Smolinski spdk_strerror(-rc)); 535524129a9SKrzysztof Smolinski goto cleanup; 536524129a9SKrzysztof Smolinski } 537524129a9SKrzysztof Smolinski 538524129a9SKrzysztof Smolinski cleanup: 539524129a9SKrzysztof Smolinski free_rpc_bdev_raid_add_base_bdev(&req); 540524129a9SKrzysztof Smolinski } 541524129a9SKrzysztof Smolinski SPDK_RPC_REGISTER("bdev_raid_add_base_bdev", rpc_bdev_raid_add_base_bdev, SPDK_RPC_RUNTIME) 542524129a9SKrzysztof Smolinski 543524129a9SKrzysztof Smolinski /* 54423850b03SKrzysztof Smolinski * Decoder object for RPC bdev_raid_remove_base_bdev 54523850b03SKrzysztof Smolinski */ 54623850b03SKrzysztof Smolinski static const struct spdk_json_object_decoder rpc_bdev_raid_remove_base_bdev_decoders[] = { 54723850b03SKrzysztof Smolinski {"name", 0, spdk_json_decode_string}, 54823850b03SKrzysztof Smolinski }; 54923850b03SKrzysztof Smolinski 55023850b03SKrzysztof Smolinski static void 55123850b03SKrzysztof Smolinski rpc_bdev_raid_remove_base_bdev_done(void *ctx, int status) 55223850b03SKrzysztof Smolinski { 55323850b03SKrzysztof Smolinski struct spdk_jsonrpc_request *request = ctx; 55423850b03SKrzysztof Smolinski 55523850b03SKrzysztof Smolinski if (status != 0) { 55623850b03SKrzysztof Smolinski spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to remove base bdev from raid bdev"); 55723850b03SKrzysztof Smolinski return; 55823850b03SKrzysztof Smolinski } 55923850b03SKrzysztof Smolinski 56023850b03SKrzysztof Smolinski spdk_jsonrpc_send_bool_response(request, true); 56123850b03SKrzysztof Smolinski } 56223850b03SKrzysztof Smolinski 56323850b03SKrzysztof Smolinski /* 56423850b03SKrzysztof Smolinski * brief: 56523850b03SKrzysztof Smolinski * bdev_raid_remove_base_bdev function is the RPC for removing base bdev from a raid bdev. 56623850b03SKrzysztof Smolinski * It takes base bdev name as input. 56723850b03SKrzysztof Smolinski * params: 56823850b03SKrzysztof Smolinski * request - pointer to json rpc request 56923850b03SKrzysztof Smolinski * params - pointer to request parameters 57023850b03SKrzysztof Smolinski * returns: 57123850b03SKrzysztof Smolinski * none 57223850b03SKrzysztof Smolinski */ 57323850b03SKrzysztof Smolinski static void 57423850b03SKrzysztof Smolinski rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, 57523850b03SKrzysztof Smolinski const struct spdk_json_val *params) 57623850b03SKrzysztof Smolinski { 5770d814d37SArtur Paszkiewicz struct spdk_bdev_desc *desc; 57823850b03SKrzysztof Smolinski char *name = NULL; 57923850b03SKrzysztof Smolinski int rc; 58023850b03SKrzysztof Smolinski 58123850b03SKrzysztof Smolinski if (spdk_json_decode_object(params, rpc_bdev_raid_remove_base_bdev_decoders, 58223850b03SKrzysztof Smolinski SPDK_COUNTOF(rpc_bdev_raid_remove_base_bdev_decoders), 58323850b03SKrzysztof Smolinski &name)) { 58423850b03SKrzysztof Smolinski spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 58523850b03SKrzysztof Smolinski "spdk_json_decode_object failed"); 58623850b03SKrzysztof Smolinski return; 58723850b03SKrzysztof Smolinski } 58823850b03SKrzysztof Smolinski 5890d814d37SArtur Paszkiewicz rc = spdk_bdev_open_ext(name, false, rpc_bdev_raid_event_cb, NULL, &desc); 59023850b03SKrzysztof Smolinski free(name); 5910d814d37SArtur Paszkiewicz if (rc != 0) { 5920d814d37SArtur Paszkiewicz goto err; 5930d814d37SArtur Paszkiewicz } 5940d814d37SArtur Paszkiewicz 5950d814d37SArtur Paszkiewicz rc = raid_bdev_remove_base_bdev(spdk_bdev_desc_get_bdev(desc), rpc_bdev_raid_remove_base_bdev_done, 5960d814d37SArtur Paszkiewicz request); 5970d814d37SArtur Paszkiewicz spdk_bdev_close(desc); 5980d814d37SArtur Paszkiewicz if (rc != 0) { 5990d814d37SArtur Paszkiewicz goto err; 6000d814d37SArtur Paszkiewicz } 6010d814d37SArtur Paszkiewicz 6020d814d37SArtur Paszkiewicz return; 6030d814d37SArtur Paszkiewicz err: 6040d814d37SArtur Paszkiewicz rpc_bdev_raid_remove_base_bdev_done(request, rc); 60523850b03SKrzysztof Smolinski } 60623850b03SKrzysztof Smolinski SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) 607f39350beSArtur Paszkiewicz 608f39350beSArtur Paszkiewicz static const struct spdk_json_object_decoder rpc_bdev_raid_options_decoders[] = { 609f39350beSArtur Paszkiewicz {"process_window_size_kb", offsetof(struct spdk_raid_bdev_opts, process_window_size_kb), spdk_json_decode_uint32, true}, 610*89fd1730Sxupeng9 {"process_max_bandwidth_mb_sec", offsetof(struct spdk_raid_bdev_opts, process_max_bandwidth_mb_sec), spdk_json_decode_uint32, true}, 611f39350beSArtur Paszkiewicz }; 612f39350beSArtur Paszkiewicz 613f39350beSArtur Paszkiewicz static void 614f39350beSArtur Paszkiewicz rpc_bdev_raid_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 615f39350beSArtur Paszkiewicz { 616f39350beSArtur Paszkiewicz struct spdk_raid_bdev_opts opts; 617f39350beSArtur Paszkiewicz int rc; 618f39350beSArtur Paszkiewicz 619f39350beSArtur Paszkiewicz raid_bdev_get_opts(&opts); 620f39350beSArtur Paszkiewicz if (params && spdk_json_decode_object(params, rpc_bdev_raid_options_decoders, 621f39350beSArtur Paszkiewicz SPDK_COUNTOF(rpc_bdev_raid_options_decoders), 622f39350beSArtur Paszkiewicz &opts)) { 623f39350beSArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 624f39350beSArtur Paszkiewicz "spdk_json_decode_object failed"); 625f39350beSArtur Paszkiewicz return; 626f39350beSArtur Paszkiewicz } 627f39350beSArtur Paszkiewicz 628f39350beSArtur Paszkiewicz rc = raid_bdev_set_opts(&opts); 629f39350beSArtur Paszkiewicz if (rc) { 630f39350beSArtur Paszkiewicz spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 631f39350beSArtur Paszkiewicz } else { 632f39350beSArtur Paszkiewicz spdk_jsonrpc_send_bool_response(request, true); 633f39350beSArtur Paszkiewicz } 634f39350beSArtur Paszkiewicz 635f39350beSArtur Paszkiewicz return; 636f39350beSArtur Paszkiewicz } 637f39350beSArtur Paszkiewicz SPDK_RPC_REGISTER("bdev_raid_set_options", rpc_bdev_raid_set_options, 638f39350beSArtur Paszkiewicz SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 639