ftl: Add rpc functionality for unmap

Trim is now also available as a management operation via RPC.

Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Change-Id: I05b778a611e9809a14bfed50b01986bb4649a35c
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13379
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:
Kozlowski Mateusz 2022-05-27 13:57:35 +02:00 committed by Jim Harris
parent 66fe5f75bb
commit 2c7c8b6ceb
9 changed files with 282 additions and 1 deletions

View File

@ -469,6 +469,7 @@ Example response:
"bdev_ftl_unload",
"bdev_ftl_create",
"bdev_ftl_load",
"bdev_ftl_unmap",
"bdev_lvol_get_lvstores",
"bdev_lvol_delete",
"bdev_lvol_resize",
@ -4912,6 +4913,46 @@ Example response:
}
~~~
### bdev_ftl_unmap {#rpc_bdev_ftl_unmap}
Unmap range of LBAs.
This RPC is subject to change.
#### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
name | Required | string | Bdev name
lba | Required | number | start lba, aligned to 1024
num_blocks | Required | number | number of blocks, aligned to 1024
#### Example
Example request:
~~~json
{
"params": {
"name": "ftl0"
"lba": "0"
"num_blocks": "1024"
},
"jsonrpc": "2.0",
"method": "bdev_ftl_unmap",
"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:

View File

@ -474,6 +474,12 @@ spdk_ftl_unmap(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_chann
}
if (lba % aligment || lba_cnt % aligment) {
if (!io) {
/* This is management/RPC path, its parameters must be aligned to 1MiB. */
return -EINVAL;
}
/* Otherwise unaligned IO requests are NOPs */
rc = ftl_io_init(ch, io, lba, lba_cnt, NULL, 0, cb_fn, cb_arg, FTL_IO_UNMAP);
if (rc) {
return rc;
@ -484,7 +490,11 @@ spdk_ftl_unmap(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_chann
return 0;
}
rc = ftl_unmap(dev, io, ch, lba, lba_cnt, cb_fn, cb_arg);
if (io) {
rc = ftl_unmap(dev, io, ch, lba, lba_cnt, cb_fn, cb_arg);
} else {
rc = ftl_mngt_unmap(dev, lba, lba_cnt, cb_fn, cb_arg);
}
return rc;
}

View File

@ -303,6 +303,23 @@ void ftl_mngt_call_process_rollback(struct ftl_mngt_process *mngt,
*/
int ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx);
/*
* The specific management functions
*/
/**
* @brief Issue unmap on FTL instance
*
* @param dev FTL device
* @param cb Caller callback
* @param cb_cntx Caller context
*
* @return Operation result
* @retval 0 The operation successful has started
* @retval Non-zero Startup failure
*/
int ftl_mngt_unmap(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
void *cb_cntx);
/**
* @brief Shuts down a FTL instance
*

View File

@ -278,6 +278,87 @@ ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void
return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx);
}
struct ftl_unmap_ctx {
uint64_t lba;
uint64_t num_blocks;
spdk_ftl_fn cb_fn;
void *cb_arg;
};
static void
ftl_mngt_process_unmap_cb(void *ctx, int status)
{
struct ftl_mngt_process *mngt = ctx;
if (status) {
ftl_mngt_fail_step(ctx);
} else {
ftl_mngt_next_step(mngt);
}
}
static void
ftl_mngt_process_unmap(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct ftl_io *io = ftl_mngt_get_process_ctx(mngt);
struct ftl_unmap_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
int rc;
if (!dev->ioch) {
ftl_mngt_fail_step(mngt);
return;
}
rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_unmap_cb, mngt);
if (rc == -EAGAIN) {
ftl_mngt_continue_step(mngt);
}
}
/*
* RPC unmap path.
*/
static const struct ftl_mngt_process_desc g_desc_unmap = {
.name = "FTL unmap",
.ctx_size = sizeof(struct ftl_io),
.steps = {
{
.name = "Process unmap",
.action = ftl_mngt_process_unmap,
},
{}
}
};
static void
ftl_mngt_unmap_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
struct ftl_unmap_ctx *ctx = _ctx;
ctx->cb_fn(ctx->cb_arg, status);
free(ctx);
}
int
ftl_mngt_unmap(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
void *cb_cntx)
{
struct ftl_unmap_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return -EAGAIN;
}
ctx->lba = lba;
ctx->num_blocks = num_blocks;
ctx->cb_fn = cb;
ctx->cb_arg = cb_cntx;
return ftl_mngt_process_execute(dev, &g_desc_unmap, ftl_mngt_unmap_cb, ctx);
}
void
ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{

View File

@ -482,6 +482,72 @@ not_found:
cb_fn(cb_arg, -ENODEV);
}
struct ftl_unmap_ctx {
struct spdk_bdev_desc *bdev;
spdk_ftl_fn cb_fn;
void *cb_arg;
};
static void
bdev_ftl_unmap_cb(void *cb_arg, int status)
{
struct ftl_unmap_ctx *ctx = cb_arg;
spdk_bdev_close(ctx->bdev);
ctx->cb_fn(ctx->cb_arg, status);
free(ctx);
}
void
bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn, void *cb_arg)
{
struct spdk_bdev_desc *ftl_bdev_desc;
struct spdk_bdev *bdev;
struct ftl_bdev *ftl;
struct ftl_unmap_ctx *ctx;
int rc;
rc = spdk_bdev_open_ext(name, false, bdev_ftl_event_cb, NULL, &ftl_bdev_desc);
if (rc) {
goto not_found;
}
bdev = spdk_bdev_desc_get_bdev(ftl_bdev_desc);
if (bdev->module != &g_ftl_if) {
rc = -ENODEV;
goto bdev_opened;
}
ctx = calloc(1, sizeof(struct ftl_unmap_ctx));
if (!ctx) {
rc = -ENOMEM;
goto bdev_opened;
}
ctx->bdev = ftl_bdev_desc;
ctx->cb_arg = cb_arg;
ctx->cb_fn = cb_fn;
ftl = bdev->ctxt;
assert(ftl);
/* It's ok to pass NULL as IO channel - FTL will detect this and use it's internal IO channel for management operations */
rc = spdk_ftl_unmap(ftl->dev, NULL, NULL, lba, num_blocks, bdev_ftl_unmap_cb, ctx);
if (rc) {
goto ctx_allocated;
}
return;
ctx_allocated:
free(ctx);
bdev_opened:
spdk_bdev_close(ftl_bdev_desc);
not_found:
cb_fn(cb_arg, rc);
}
static void
bdev_ftl_finish(void)
{

View File

@ -24,5 +24,7 @@ int bdev_ftl_create_bdev(const struct spdk_ftl_conf *conf, ftl_bdev_init_fn cb,
void bdev_ftl_delete_bdev(const char *name, bool fast_shutdown, spdk_bdev_unregister_cb cb_fn,
void *cb_arg);
int bdev_ftl_defer_init(const struct spdk_ftl_conf *conf);
void bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn,
void *cb_arg);
#endif /* SPDK_BDEV_FTL_H */

View File

@ -172,3 +172,41 @@ rpc_bdev_ftl_unload(struct spdk_jsonrpc_request *request,
rpc_bdev_ftl_delete(request, params);
}
SPDK_RPC_REGISTER("bdev_ftl_unload", rpc_bdev_ftl_unload, SPDK_RPC_RUNTIME)
struct rpc_ftl_unmap {
char *name;
uint64_t lba;
uint64_t num_blocks;
};
static const struct spdk_json_object_decoder rpc_ftl_unmap_decoders[] = {
{"name", offsetof(struct rpc_delete_ftl, name), spdk_json_decode_string},
{"lba", offsetof(struct rpc_ftl_unmap, lba), spdk_json_decode_uint64, true},
{"num_blocks", offsetof(struct rpc_ftl_unmap, num_blocks), spdk_json_decode_uint64, true},
};
static void
rpc_bdev_ftl_unmap_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_unmap(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
{
struct rpc_ftl_unmap attrs = {};
if (spdk_json_decode_object(params, rpc_ftl_unmap_decoders, SPDK_COUNTOF(rpc_ftl_unmap_decoders),
&attrs)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
goto invalid;
}
bdev_ftl_unmap(attrs.name, attrs.lba, attrs.num_blocks, rpc_bdev_ftl_unmap_cb, request);
invalid:
free(attrs.name);
}
SPDK_RPC_REGISTER("bdev_ftl_unmap", rpc_bdev_ftl_unmap, SPDK_RPC_RUNTIME)

View File

@ -1401,6 +1401,21 @@ def bdev_ftl_delete(client, name, fast_shutdown):
return client.call('bdev_ftl_delete', params)
def bdev_ftl_unmap(client, name, lba, num_blocks):
"""FTL unmap
Args:
name: name of the bdev
lba: starting lba to be unmapped
num_blocks: number of blocks to unmap
"""
params = {'name': name,
'lba': lba,
'num_blocks': num_blocks}
return client.call('bdev_ftl_unmap', params)
def bdev_get_bdevs(client, name=None, timeout=None):
"""Get information about block devices.

View File

@ -2072,6 +2072,17 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('-f', '--fast-shutdown', help="Fast shutdown", action='store_true')
p.set_defaults(func=bdev_ftl_delete)
def bdev_ftl_unmap(args):
print_dict(rpc.bdev.bdev_ftl_unmap(args.client, name=args.name,
lba=args.lba,
num_blocks=args.num_blocks))
p = subparsers.add_parser('bdev_ftl_unmap', help='FTL unmap')
p.add_argument('-b', '--name', help="Name of the bdev", required=True)
p.add_argument('--lba', help='start LBA', required=True, type=int)
p.add_argument('--num-blocks', help='num blocks', required=True, type=int)
p.set_defaults(func=bdev_ftl_unmap)
# vmd
def vmd_enable(args):
print_dict(rpc.vmd.vmd_enable(args.client))