From 5bdaec63224663ecd58e9d4c82589f17b0afc5e0 Mon Sep 17 00:00:00 2001 From: Rafal Stefanowski Date: Sun, 21 Feb 2021 05:25:32 +0100 Subject: [PATCH] ocf/rpc: Add bdev_ocf_set_cache_mode method This method allows to dynamically switch cache mode on OCF bdev Signed-off-by: Rafal Stefanowski Change-Id: I933273e35bb9f29528657f8f6800c6b52dde32e5 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6547 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Tomasz Zawadzki Reviewed-by: Shuhei Matsumoto --- doc/jsonrpc.md | 41 ++++++++++++ module/bdev/ocf/vbdev_ocf.c | 25 ++++++++ module/bdev/ocf/vbdev_ocf.h | 7 +++ module/bdev/ocf/vbdev_ocf_rpc.c | 69 +++++++++++++++++++++ scripts/rpc.py | 10 +++ scripts/rpc/bdev.py | 18 ++++++ test/ocf/management/configuration-change.sh | 29 +++++++++ test/ocf/ocf.sh | 1 + 8 files changed, 200 insertions(+) create mode 100755 test/ocf/management/configuration-change.sh diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 5c32d3cb2..fa5409024 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -2232,6 +2232,47 @@ Example response: } ~~~ +## bdev_ocf_set_cache_mode {#rpc_bdev_ocf_set_cache_mode} + +Set new cache mode on OCF bdev. + +### Parameters + +Name | Optional | Type | Description +----------------------- | -------- | ----------- | ----------- +name | Required | string | Bdev name +mode | Required | string | OCF cache mode: wb, wt, pt, wa, wi, wo + +### Response + +New cache mode name. + +### Example + +Example request: + +~~~ +{ + "params": { + "name": "ocf0", + "mode": "pt", + }, + "jsonrpc": "2.0", + "method": "bdev_ocf_set_cache_mode", + "id": 1 +} +~~~ + +Example response: + +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": "pt" +} +~~~ + ## bdev_malloc_create {#rpc_bdev_malloc_create} Construct @ref bdev_config_malloc diff --git a/module/bdev/ocf/vbdev_ocf.c b/module/bdev/ocf/vbdev_ocf.c index a5b285468..fcc7ef3ee 100644 --- a/module/bdev/ocf/vbdev_ocf.c +++ b/module/bdev/ocf/vbdev_ocf.c @@ -1479,6 +1479,31 @@ vbdev_ocf_construct(const char *vbdev_name, } } +/* Set new cache mode on OCF cache */ +void +vbdev_ocf_set_cache_mode(struct vbdev_ocf *vbdev, + const char *cache_mode_name, + void (*cb)(int, struct vbdev_ocf *, void *), + void *cb_arg) +{ + ocf_cache_t cache; + ocf_cache_mode_t cache_mode; + int rc; + + cache = vbdev->ocf_cache; + cache_mode = ocf_get_cache_mode(cache_mode_name); + + rc = ocf_mngt_cache_trylock(cache); + if (rc) { + cb(rc, vbdev, cb_arg); + return; + } + + rc = ocf_mngt_cache_set_mode(cache, cache_mode); + ocf_mngt_cache_unlock(cache); + cb(rc, vbdev, cb_arg); +} + /* This called if new device is created in SPDK application * If that device named as one of base bdevs of OCF vbdev, * claim and open them */ diff --git a/module/bdev/ocf/vbdev_ocf.h b/module/bdev/ocf/vbdev_ocf.h index b313e9e0c..fb980f4ba 100644 --- a/module/bdev/ocf/vbdev_ocf.h +++ b/module/bdev/ocf/vbdev_ocf.h @@ -203,6 +203,13 @@ int vbdev_ocf_delete(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_ int vbdev_ocf_delete_clean(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg); +/* Set new cache mode on OCF cache */ +void vbdev_ocf_set_cache_mode( + struct vbdev_ocf *vbdev, + const char *cache_mode_name, + void (*cb)(int, struct vbdev_ocf *, void *), + void *cb_arg); + typedef void (*vbdev_ocf_foreach_fn)(struct vbdev_ocf *, void *); /* Execute fn for each OCF device that is online or waits for base devices */ diff --git a/module/bdev/ocf/vbdev_ocf_rpc.c b/module/bdev/ocf/vbdev_ocf_rpc.c index 9e07a200a..315f13138 100644 --- a/module/bdev/ocf/vbdev_ocf_rpc.c +++ b/module/bdev/ocf/vbdev_ocf_rpc.c @@ -33,6 +33,7 @@ #include "vbdev_ocf.h" #include "stats.h" +#include "utils.h" #include "spdk/log.h" #include "spdk/rpc.h" #include "spdk/string.h" @@ -359,3 +360,71 @@ end: } SPDK_RPC_REGISTER("bdev_ocf_get_bdevs", rpc_bdev_ocf_get_bdevs, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_ocf_get_bdevs, get_ocf_bdevs) + +/* Structure to hold the parameters for this RPC method. */ +struct rpc_bdev_ocf_set_cache_mode { + char *name; /* main vbdev name */ + char *mode; /* OCF cache mode to switch to */ +}; + +static void +free_rpc_bdev_ocf_set_cache_mode(struct rpc_bdev_ocf_set_cache_mode *r) +{ + free(r->name); + free(r->mode); +} + +/* Structure to decode the input parameters for this RPC method. */ +static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cache_mode_decoders[] = { + {"name", offsetof(struct rpc_bdev_ocf_set_cache_mode, name), spdk_json_decode_string}, + {"mode", offsetof(struct rpc_bdev_ocf_set_cache_mode, mode), spdk_json_decode_string}, +}; + +static void +cache_mode_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg) +{ + struct spdk_jsonrpc_request *request = cb_arg; + struct spdk_json_write_ctx *w; + + if (status) { + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "Could not change OCF vbdev cache mode: %d", + status); + } else { + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_string(w, ocf_get_cache_modename( + ocf_cache_get_mode(vbdev->ocf_cache))); + spdk_jsonrpc_end_result(request, w); + } +} + +static void +rpc_bdev_ocf_set_cache_mode(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_bdev_ocf_set_cache_mode req = {NULL}; + struct vbdev_ocf *vbdev; + int status; + + status = spdk_json_decode_object(params, rpc_bdev_ocf_set_cache_mode_decoders, + SPDK_COUNTOF(rpc_bdev_ocf_set_cache_mode_decoders), + &req); + if (status) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid parameters"); + goto end; + } + + vbdev = vbdev_ocf_get_by_name(req.name); + if (vbdev == NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + spdk_strerror(ENODEV)); + goto end; + } + + vbdev_ocf_set_cache_mode(vbdev, req.mode, cache_mode_cb, request); + +end: + free_rpc_bdev_ocf_set_cache_mode(&req); +} +SPDK_RPC_REGISTER("bdev_ocf_set_cache_mode", rpc_bdev_ocf_set_cache_mode, SPDK_RPC_RUNTIME) diff --git a/scripts/rpc.py b/scripts/rpc.py index f85712f3c..74ca255c7 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -325,6 +325,16 @@ if __name__ == "__main__": p.add_argument('name', nargs='?', default=None, help='name of OCF vbdev or name of cache device or name of core device (optional)') p.set_defaults(func=bdev_ocf_get_bdevs) + def bdev_ocf_set_cache_mode(args): + print_json(rpc.bdev.bdev_ocf_set_cache_mode(args.client, + name=args.name, + mode=args.mode)) + p = subparsers.add_parser('bdev_ocf_set_cache_mode', + help='Set cache mode of OCF block device') + p.add_argument('name', help='Name of OCF bdev') + p.add_argument('mode', help='OCF cache mode', choices=['wb', 'wt', 'pt', 'wa', 'wi', 'wo']) + p.set_defaults(func=bdev_ocf_set_cache_mode) + def bdev_malloc_create(args): num_blocks = (args.total_size * 1024 * 1024) // args.block_size print_json(rpc.bdev.bdev_malloc_create(args.client, diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 26c2bc92d..df9f606e8 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -204,6 +204,24 @@ def bdev_ocf_get_bdevs(client, name=None): return client.call('bdev_ocf_get_bdevs', params) +def bdev_ocf_set_cache_mode(client, name, mode): + """Set cache mode of OCF block device + + Args: + name: name of OCF bdev + mode: OCF cache mode: {'wb', 'wt', 'pt', 'wa', 'wi', 'wo'} + + Returns: + New cache mode name + """ + params = { + 'name': name, + 'mode': mode, + } + + return client.call('bdev_ocf_set_cache_mode', params) + + @deprecated_alias('construct_malloc_bdev') def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None): """Construct a malloc block device. diff --git a/test/ocf/management/configuration-change.sh b/test/ocf/management/configuration-change.sh new file mode 100755 index 000000000..e307d9b41 --- /dev/null +++ b/test/ocf/management/configuration-change.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +curdir=$(dirname $(readlink -f "${BASH_SOURCE[0]}")) +rootdir=$(readlink -f $curdir/../../..) +source $rootdir/test/common/autotest_common.sh + +rpc_py=$rootdir/scripts/rpc.py +cache_modes=(wt wb pt wa wi wo) + +$SPDK_BIN_DIR/iscsi_tgt & +spdk_pid=$! + +waitforlisten $spdk_pid + +# Prepare OCF cache +$rpc_py bdev_malloc_create 101 512 -b Malloc0 +$rpc_py bdev_malloc_create 101 512 -b Malloc1 +$rpc_py bdev_ocf_create Cache wt Malloc0 Malloc1 + +$rpc_py bdev_ocf_get_bdevs | jq -e \ + '.[0] | .started and .cache.attached and .core.attached' + +# Change cache mode +for cache_mode in "${cache_modes[@]}"; do + $rpc_py bdev_ocf_set_cache_mode Cache $cache_mode +done + +trap - SIGINT SIGTERM EXIT +killprocess $spdk_pid diff --git a/test/ocf/ocf.sh b/test/ocf/ocf.sh index 415befc67..dd81371f3 100755 --- a/test/ocf/ocf.sh +++ b/test/ocf/ocf.sh @@ -12,3 +12,4 @@ run_test "ocf_create_destruct" "$testdir/management/create-destruct.sh" run_test "ocf_multicore" "$testdir/management/multicore.sh" run_test "ocf_persistent_metadata" "$testdir/management/persistent-metadata.sh" run_test "ocf_remove" "$testdir/management/remove.sh" +run_test "ocf_configuration_change" "$testdir/management/configuration-change.sh"