FTL: Add bdev_ftl_create and delete rpc definitions
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com> Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Change-Id: I0837028fbe349e8df7f05fb3c9db1f4682f04679 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13301 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
6db3ac3a8e
commit
be90ea6e7b
116
doc/jsonrpc.md
116
doc/jsonrpc.md
@ -465,7 +465,9 @@ Example response:
|
||||
"bdev_malloc_delete",
|
||||
"bdev_malloc_create",
|
||||
"bdev_ftl_delete",
|
||||
"bdev_ftl_unload",
|
||||
"bdev_ftl_create",
|
||||
"bdev_ftl_load",
|
||||
"bdev_lvol_get_lvstores",
|
||||
"bdev_lvol_delete",
|
||||
"bdev_lvol_resize",
|
||||
@ -4564,11 +4566,11 @@ This RPC is subject to change.
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | Bdev name
|
||||
trtype | Required | string | Transport type
|
||||
traddr | Required | string | NVMe target address
|
||||
punits | Required | string | Parallel unit range in the form of start-end e.g 4-8
|
||||
base_bdev | Required | string | Name of the base device
|
||||
cache | Required | string | Name of the cache device
|
||||
uuid | Optional | string | UUID of restored bdev (not applicable when creating new instance)
|
||||
cache | Optional | string | Name of the bdev to be used as a write buffer cache
|
||||
core_mask | Optional | string | CPU core(s) possible for placement of the ftl core thread, application main thread by default
|
||||
overprovisioning | Optional | int | Percentage of base device used for relocation, 20% by default
|
||||
|
||||
#### Result
|
||||
|
||||
@ -4581,11 +4583,12 @@ Example request:
|
||||
~~~json
|
||||
{
|
||||
"params": {
|
||||
"name": "nvme0"
|
||||
"trtype" "pcie"
|
||||
"traddr": "0000:00:04.0"
|
||||
"punits": "0-3"
|
||||
"uuid": "4a7481ce-786f-41a0-9b86-8f7465c8f4d3"
|
||||
"name": "ftl0",
|
||||
"base_bdev": "nvme0n1",
|
||||
"cache": "nvme1n1",
|
||||
"uuid": "4a7481ce-786f-41a0-9b86-8f7465c8f4d3",
|
||||
"core_mask": "[0]",
|
||||
"overprovisioning": 10
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_ftl_create",
|
||||
@ -4600,7 +4603,61 @@ Example response:
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"name" : "nvme0"
|
||||
"name" : "ftl0"
|
||||
"uuid" : "4a7481ce-786f-41a0-9b86-8f7465c8f4d3"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_ftl_load {#rpc_bdev_ftl_load}
|
||||
|
||||
Loads FTL bdev.
|
||||
|
||||
This RPC is subject to change.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | Bdev name
|
||||
base_bdev | Required | string | Name of the base device
|
||||
cache | Required | string | Name of the cache device
|
||||
uuid | Required | string | UUID of restored bdev
|
||||
core_mask | Optional | string | CPU core(s) possible for placement of the ftl core thread, application main thread by default
|
||||
overprovisioning | Optional | int | Percentage of base device used for relocation, 20% by default
|
||||
|
||||
#### Result
|
||||
|
||||
Name of loaded bdev.
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"params": {
|
||||
"name": "ftl0",
|
||||
"base_bdev": "nvme0n1",
|
||||
"cache": "nvme1n1",
|
||||
"uuid": "4a7481ce-786f-41a0-9b86-8f7465c8f4d3",
|
||||
"core_mask": "[0]",
|
||||
"overprovisioning": 10
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_ftl_load",
|
||||
"id": 1
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"name" : "ftl0"
|
||||
"uuid" : "4a7481ce-786f-41a0-9b86-8f7465c8f4d3"
|
||||
}
|
||||
}
|
||||
@ -4625,7 +4682,7 @@ Example request:
|
||||
~~~json
|
||||
{
|
||||
"params": {
|
||||
"name": "nvme0"
|
||||
"name": "ftl0"
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_ftl_delete",
|
||||
@ -4643,6 +4700,43 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_ftl_unload {#rpc_bdev_ftl_unload}
|
||||
|
||||
Unloads FTL bdev.
|
||||
|
||||
This RPC is subject to change.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | Bdev name
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"params": {
|
||||
"name": "ftl0"
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_ftl_unload",
|
||||
"id": 1
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_pmem_create_pool {#rpc_bdev_pmem_create_pool}
|
||||
|
||||
Create a @ref bdev_config_pmem blk pool file. It is equivalent of following `pmempool create` command:
|
||||
|
@ -110,7 +110,7 @@ endif
|
||||
|
||||
# module/bdev
|
||||
ifeq ($(OS),Linux)
|
||||
DEPDIRS-bdev_ftl := bdev json log util ftl
|
||||
DEPDIRS-bdev_ftl := $(BDEV_DEPS) ftl
|
||||
endif
|
||||
DEPDIRS-bdev_gpt := bdev json log thread util
|
||||
|
||||
|
@ -15,7 +15,7 @@ ifdef SPDK_FTL_VSS_EMU
|
||||
CFLAGS += -DSPDK_FTL_VSS_EMU
|
||||
endif
|
||||
|
||||
C_SRCS += bdev_ftl.c
|
||||
C_SRCS += bdev_ftl.c bdev_ftl_rpc.c
|
||||
LIBNAME = bdev_ftl
|
||||
|
||||
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
|
||||
|
161
module/bdev/ftl/bdev_ftl_rpc.c
Normal file
161
module/bdev/ftl/bdev_ftl_rpc.c
Normal file
@ -0,0 +1,161 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/bdev_module.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/log.h"
|
||||
|
||||
#include "bdev_ftl.h"
|
||||
|
||||
static int
|
||||
rpc_bdev_ftl_decode_uuid(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
char *uuid_str;
|
||||
int ret;
|
||||
|
||||
uuid_str = spdk_json_strdup(val);
|
||||
if (!uuid_str) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = spdk_uuid_parse(out, uuid_str);
|
||||
|
||||
free(uuid_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_ftl_create_decoders[] = {
|
||||
{"name", offsetof(struct spdk_ftl_conf, name), spdk_json_decode_string},
|
||||
{"base_bdev", offsetof(struct spdk_ftl_conf, base_bdev), spdk_json_decode_string},
|
||||
{"uuid", offsetof(struct spdk_ftl_conf, uuid), rpc_bdev_ftl_decode_uuid, true},
|
||||
{"cache", offsetof(struct spdk_ftl_conf, cache_bdev), spdk_json_decode_string},
|
||||
{
|
||||
"overprovisioning", offsetof(struct spdk_ftl_conf, overprovisioning),
|
||||
spdk_json_decode_uint64, true
|
||||
},
|
||||
{
|
||||
"core_mask", offsetof(struct spdk_ftl_conf, core_mask),
|
||||
spdk_json_decode_string, true
|
||||
},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_create_cb(const struct ftl_bdev_info *bdev_info, void *ctx, int status)
|
||||
{
|
||||
struct spdk_jsonrpc_request *request = ctx;
|
||||
char bdev_uuid[SPDK_UUID_STRING_LEN];
|
||||
struct spdk_json_write_ctx *w;
|
||||
|
||||
if (status) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to create FTL bdev: %s",
|
||||
spdk_strerror(-status));
|
||||
return;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), &bdev_info->uuid);
|
||||
spdk_json_write_object_begin(w);
|
||||
spdk_json_write_named_string(w, "name", bdev_info->name);
|
||||
spdk_json_write_named_string(w, "uuid", bdev_uuid);
|
||||
spdk_json_write_object_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct spdk_ftl_conf conf = {};
|
||||
struct spdk_json_write_ctx *w;
|
||||
int rc;
|
||||
|
||||
spdk_ftl_get_default_conf(&conf);
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_ftl_create_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_ftl_create_decoders),
|
||||
&conf)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (spdk_mem_all_zero(&conf.uuid, sizeof(conf.uuid))) {
|
||||
conf.mode |= SPDK_FTL_MODE_CREATE;
|
||||
}
|
||||
|
||||
rc = bdev_ftl_create_bdev(&conf, rpc_bdev_ftl_create_cb, request);
|
||||
if (rc == -ENODEV) {
|
||||
rc = bdev_ftl_defer_init(&conf);
|
||||
if (rc == 0) {
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", conf.name);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to create FTL bdev: %s",
|
||||
spdk_strerror(-rc));
|
||||
}
|
||||
out:
|
||||
spdk_ftl_conf_deinit(&conf);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_ftl_create", rpc_bdev_ftl_create, SPDK_RPC_RUNTIME)
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_load(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
rpc_bdev_ftl_create(request, params);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_ftl_load", rpc_bdev_ftl_load, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_delete_ftl {
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = {
|
||||
{"name", offsetof(struct rpc_delete_ftl, name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno)
|
||||
{
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
|
||||
spdk_jsonrpc_send_bool_response(request, bdeverrno == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_delete_ftl attrs = {};
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_delete_ftl_decoders,
|
||||
SPDK_COUNTOF(rpc_delete_ftl_decoders),
|
||||
&attrs)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
bdev_ftl_delete_bdev(attrs.name, rpc_bdev_ftl_delete_cb, request);
|
||||
invalid:
|
||||
free(attrs.name);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_ftl_delete", rpc_bdev_ftl_delete, SPDK_RPC_RUNTIME)
|
||||
|
||||
static void
|
||||
rpc_bdev_ftl_unload(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
rpc_bdev_ftl_delete(request, params);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_ftl_unload", rpc_bdev_ftl_unload, SPDK_RPC_RUNTIME)
|
@ -1347,6 +1347,34 @@ def bdev_ftl_create(client, name, base_bdev, **kwargs):
|
||||
return client.call('bdev_ftl_create', params)
|
||||
|
||||
|
||||
def bdev_ftl_load(client, name, base_bdev, **kwargs):
|
||||
"""Load FTL bdev
|
||||
|
||||
Args:
|
||||
name: name of the bdev
|
||||
base_bdev: name of the base bdev
|
||||
kwargs: optional parameters
|
||||
"""
|
||||
params = {'name': name,
|
||||
'base_bdev': base_bdev}
|
||||
for key, value in kwargs.items():
|
||||
if value is not None:
|
||||
params[key] = value
|
||||
|
||||
return client.call('bdev_ftl_load', params)
|
||||
|
||||
|
||||
def bdev_ftl_unload(client, name):
|
||||
"""Unload FTL bdev
|
||||
|
||||
Args:
|
||||
name: name of the bdev
|
||||
"""
|
||||
params = {'name': name}
|
||||
|
||||
return client.call('bdev_ftl_unload', params)
|
||||
|
||||
|
||||
def bdev_ftl_delete(client, name):
|
||||
"""Delete FTL bdev
|
||||
|
||||
|
@ -1993,58 +1993,58 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.set_defaults(func=bdev_split_delete)
|
||||
|
||||
# ftl
|
||||
ftl_valid_limits = ('crit', 'high', 'low', 'start')
|
||||
|
||||
def bdev_ftl_create(args):
|
||||
def parse_limits(limits, arg_dict, key_suffix=''):
|
||||
for limit in limits.split(','):
|
||||
key, value = limit.split(':', 1)
|
||||
if key in ftl_valid_limits:
|
||||
arg_dict['limit_' + key + key_suffix] = int(value)
|
||||
else:
|
||||
raise ValueError('Limit {} is not supported'.format(key))
|
||||
|
||||
arg_limits = {}
|
||||
if args.limit_threshold:
|
||||
parse_limits(args.limit_threshold, arg_limits, '_threshold')
|
||||
|
||||
if args.limit:
|
||||
parse_limits(args.limit, arg_limits)
|
||||
|
||||
print_dict(rpc.bdev.bdev_ftl_create(args.client,
|
||||
name=args.name,
|
||||
base_bdev=args.base_bdev,
|
||||
uuid=args.uuid,
|
||||
cache=args.cache,
|
||||
allow_open_bands=args.allow_open_bands,
|
||||
overprovisioning=args.overprovisioning,
|
||||
l2p_path=args.l2p_path,
|
||||
use_append=args.use_append,
|
||||
**arg_limits))
|
||||
core_mask=args.core_mask))
|
||||
|
||||
p = subparsers.add_parser('bdev_ftl_create', help='Add FTL bdev')
|
||||
p.add_argument('-b', '--name', help="Name of the bdev", required=True)
|
||||
p.add_argument('-d', '--base-bdev', help='Name of zoned bdev used as underlying device',
|
||||
p.add_argument('-d', '--base-bdev', help='Name of bdev used as underlying device',
|
||||
required=True)
|
||||
p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new '
|
||||
'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)')
|
||||
p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)')
|
||||
p.add_argument('-o', '--allow-open-bands', help='Restoring after dirty shutdown without cache will'
|
||||
' result in partial data recovery, instead of error', action='store_true')
|
||||
p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache',
|
||||
required=True)
|
||||
p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed'
|
||||
' to user (optional)', type=int)
|
||||
p.add_argument('--l2p-path', help='Path to persistent memory file or device to store l2p onto, '
|
||||
'by default l2p is kept in DRAM and is volatile (optional)')
|
||||
p.add_argument('--use-append', help='Use appends instead of writes', action='store_true')
|
||||
|
||||
limits = p.add_argument_group('Defrag limits', 'Configures defrag limits and thresholds for'
|
||||
' levels ' + str(ftl_valid_limits)[1:-1])
|
||||
limits.add_argument('--limit', help='Percentage of allowed user versus internal writes at given'
|
||||
' levels, e.g. crit:0,high:20,low:80')
|
||||
limits.add_argument('--limit-threshold', help='Number of free bands triggering a given level of'
|
||||
' write limiting e.g. crit:1,high:2,low:3,start:4')
|
||||
' to user (optional); default 20', type=int)
|
||||
p.add_argument('--core-mask', help='CPU core mask - which cores will be used for ftl core thread, '
|
||||
'by default core thread will be set to the main application core (optional)')
|
||||
p.set_defaults(func=bdev_ftl_create)
|
||||
|
||||
def bdev_ftl_load(args):
|
||||
print_dict(rpc.bdev.bdev_ftl_load(args.client,
|
||||
name=args.name,
|
||||
base_bdev=args.base_bdev,
|
||||
uuid=args.uuid,
|
||||
cache=args.cache,
|
||||
overprovisioning=args.overprovisioning,
|
||||
core_mask=args.core_mask))
|
||||
|
||||
p = subparsers.add_parser('bdev_ftl_load', help='Load FTL bdev')
|
||||
p.add_argument('-b', '--name', help="Name of the bdev", required=True)
|
||||
p.add_argument('-d', '--base-bdev', help='Name of bdev used as underlying device',
|
||||
required=True)
|
||||
p.add_argument('-u', '--uuid', help='UUID of restored bdev', required=True)
|
||||
p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache',
|
||||
required=True)
|
||||
p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed'
|
||||
' to user (optional); default 20', type=int)
|
||||
p.add_argument('--core-mask', help='CPU core mask - which cores will be used for ftl core thread, '
|
||||
'by default core thread will be set to the main application core (optional)')
|
||||
p.set_defaults(func=bdev_ftl_load)
|
||||
|
||||
def bdev_ftl_unload(args):
|
||||
print_dict(rpc.bdev.bdev_ftl_unload(args.client, name=args.name))
|
||||
|
||||
p = subparsers.add_parser('bdev_ftl_unload', help='Unload FTL bdev')
|
||||
p.add_argument('-b', '--name', help="Name of the bdev", required=True)
|
||||
p.set_defaults(func=bdev_ftl_unload)
|
||||
|
||||
def bdev_ftl_delete(args):
|
||||
print_dict(rpc.bdev.bdev_ftl_delete(args.client, name=args.name))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user