From 195be29e9b83ed2d063af7dc2dbeeef9607d6d7d Mon Sep 17 00:00:00 2001 From: Mateusz Kozlowski Date: Mon, 19 Aug 2019 13:36:42 +0200 Subject: [PATCH] bdev/zone: Rpc functions for zoned block bdev Added rpc handling for creation and deletion of zoned block bdev Signed-off-by: Mateusz Kozlowski Change-Id: Ib7b6f3928511aa840cbe098472682c951e92e5ed Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468031 Community-CI: Broadcom SPDK FC-NVMe CI Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Tomasz Zawadzki Reviewed-by: Jim Harris --- mk/spdk.lib_deps.mk | 2 +- module/bdev/zone_block/Makefile | 2 +- module/bdev/zone_block/vbdev_zone_block_rpc.c | 146 ++++++++++++++++++ scripts/rpc.py | 23 +++ scripts/rpc/bdev.py | 30 ++++ 5 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 module/bdev/zone_block/vbdev_zone_block_rpc.c diff --git a/mk/spdk.lib_deps.mk b/mk/spdk.lib_deps.mk index bbd5a9c67..2b1d63d8a 100644 --- a/mk/spdk.lib_deps.mk +++ b/mk/spdk.lib_deps.mk @@ -112,7 +112,7 @@ DEPDIRS-bdev_gpt := bdev conf json log thread util DEPDIRS-bdev_lvol := $(BDEV_DEPS) lvol blob blob_bdev DEPDIRS-bdev_rpc := $(BDEV_DEPS) -DEPDIRS-bdev_zone_block := bdev log +DEPDIRS-bdev_zone_block := $(BDEV_DEPS) DEPDIRS-bdev_error := $(BDEV_DEPS_CONF) DEPDIRS-bdev_malloc := $(BDEV_DEPS_CONF) copy diff --git a/module/bdev/zone_block/Makefile b/module/bdev/zone_block/Makefile index 686ad1c90..1b098e1fe 100644 --- a/module/bdev/zone_block/Makefile +++ b/module/bdev/zone_block/Makefile @@ -34,7 +34,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -C_SRCS = vbdev_zone_block.c +C_SRCS = vbdev_zone_block.c vbdev_zone_block_rpc.c LIBNAME = bdev_zone_block include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/module/bdev/zone_block/vbdev_zone_block_rpc.c b/module/bdev/zone_block/vbdev_zone_block_rpc.c new file mode 100644 index 000000000..b962cff5e --- /dev/null +++ b/module/bdev/zone_block/vbdev_zone_block_rpc.c @@ -0,0 +1,146 @@ +/*- + * 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/stdinc.h" + +#include "vbdev_zone_block.h" + +#include "spdk/util.h" +#include "spdk/string.h" +#include "spdk/rpc.h" + +#include "spdk_internal/log.h" + +struct rpc_construct_zone_block { + char *name; + char *base_bdev; + uint64_t zone_capacity; + uint64_t optimal_open_zones; +}; + +static void +free_rpc_construct_zone_block(struct rpc_construct_zone_block *req) +{ + free(req->name); + free(req->base_bdev); +} + +static const struct spdk_json_object_decoder rpc_construct_zone_block_decoders[] = { + {"name", offsetof(struct rpc_construct_zone_block, name), spdk_json_decode_string}, + {"base_bdev", offsetof(struct rpc_construct_zone_block, base_bdev), spdk_json_decode_string}, + {"zone_capacity", offsetof(struct rpc_construct_zone_block, zone_capacity), spdk_json_decode_uint64}, + {"optimal_open_zones", offsetof(struct rpc_construct_zone_block, optimal_open_zones), spdk_json_decode_uint64}, +}; + +static void +rpc_zone_block_create(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_construct_zone_block req = {}; + struct spdk_json_write_ctx *w; + int rc; + + if (spdk_json_decode_object(params, rpc_construct_zone_block_decoders, + SPDK_COUNTOF(rpc_construct_zone_block_decoders), + &req)) { + SPDK_ERRLOG("Failed to decode block create parameters"); + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid parameters"); + goto cleanup; + } + + rc = spdk_vbdev_zone_block_create(req.base_bdev, req.name, req.zone_capacity, + req.optimal_open_zones); + if (rc) { + SPDK_ERRLOG("Failed to create block zoned vbdev: %s", spdk_strerror(-rc)); + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "Failed to create block zoned vbdev: %s", + spdk_strerror(-rc)); + goto cleanup; + } + + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_string(w, req.name); + spdk_jsonrpc_end_result(request, w); + +cleanup: + free_rpc_construct_zone_block(&req); +} +SPDK_RPC_REGISTER("bdev_zone_block_create", rpc_zone_block_create, SPDK_RPC_RUNTIME) + +struct rpc_delete_zone_block { + char *name; +}; + +static void +free_rpc_delete_zone_block(struct rpc_delete_zone_block *req) +{ + free(req->name); +} + +static const struct spdk_json_object_decoder rpc_delete_zone_block_decoders[] = { + {"name", offsetof(struct rpc_delete_zone_block, name), spdk_json_decode_string}, +}; + +static void +_rpc_delete_zone_block_cb(void *cb_ctx, int rc) +{ + struct spdk_jsonrpc_request *request = cb_ctx; + struct spdk_json_write_ctx *w; + + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_bool(w, rc == 0); + spdk_jsonrpc_end_result(request, w); +} + +static void +rpc_zone_block_delete(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_delete_zone_block attrs = {}; + + if (spdk_json_decode_object(params, rpc_delete_zone_block_decoders, + SPDK_COUNTOF(rpc_delete_zone_block_decoders), + &attrs)) { + SPDK_ERRLOG("Failed to decode block delete parameters"); + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid parameters"); + goto cleanup; + } + + spdk_vbdev_zone_block_delete(attrs.name, _rpc_delete_zone_block_cb, request); + +cleanup: + free_rpc_delete_zone_block(&attrs); +} +SPDK_RPC_REGISTER("bdev_zone_block_delete", rpc_zone_block_delete, SPDK_RPC_RUNTIME) diff --git a/scripts/rpc.py b/scripts/rpc.py index 5c9f25a0e..53df463bd 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -473,6 +473,29 @@ if __name__ == "__main__": help='Name of the NVMe controller. Example: Nvme0', required=True) p.set_defaults(func=bdev_nvme_cuse_unregister) + def bdev_zone_block_create(args): + print_json(rpc.bdev.bdev_zone_block_create(args.client, + name=args.name, + base_bdev=args.base_bdev, + zone_capacity=args.zone_capacity, + optimal_open_zones=args.optimal_open_zones)) + + p = subparsers.add_parser('bdev_zone_block_create', + help='Create virtual zone namespace device with block device backend') + p.add_argument('-b', '--name', help="Name of the zone device", required=True) + p.add_argument('-n', '--base-bdev', help='Name of underlying, non-zoned bdev', required=True) + p.add_argument('-z', '--zone-capacity', help='Surfaced zone capacity in blocks', type=int, required=True) + p.add_argument('-o', '--optimal-open-zones', help='Number of zones required to reach optimal write speed', type=int, required=True) + p.set_defaults(func=bdev_zone_block_create) + + def bdev_zone_block_delete(args): + rpc.bdev.bdev_zone_block_delete(args.client, + name=args.name) + + p = subparsers.add_parser('bdev_zone_block_delete', help='Delete a virtual zone namespace device') + p.add_argument('name', help='Virtual zone bdev name') + p.set_defaults(func=bdev_zone_block_delete) + def bdev_rbd_create(args): config = None if args.config: diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index ef1822a1b..7743d03ac 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -510,6 +510,36 @@ def bdev_nvme_cuse_unregister(client, name): return client.call('bdev_nvme_cuse_unregister', params) +def bdev_zone_block_create(client, name, base_bdev, zone_capacity, optimal_open_zones): + """Creates a virtual zone device on top of existing non-zoned bdev. + + Args: + name: Zone device name + base_bdev: Base Nvme bdev name + zone_capacity: Surfaced zone capacity in blocks + optimal_open_zones: Number of zones required to reach optimal write speed (optional, default: 1) + + Returns: + Name of created block device. + """ + params = {'name': name, + 'base_bdev': base_bdev, + 'zone_capacity': zone_capacity, + 'optimal_open_zones': optimal_open_zones} + + return client.call('bdev_zone_block_create', params) + + +def bdev_zone_block_delete(client, name): + """Remove block zone bdev from the system. + + Args: + name: name of block zone bdev to delete + """ + params = {'name': name} + return client.call('bdev_zone_block_delete', params) + + @deprecated_alias('construct_rbd_bdev') def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=None, config=None): """Create a Ceph RBD block device.