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:
parent
66fe5f75bb
commit
2c7c8b6ceb
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user