bdev: add timeout option to bdev_get_bdevs RPC
This opption allows the bdev_get_bdevs RPC to block until a bdev with specified name appears. It can be useful, when a bdev is created asynchronously and the exact moment at which it appears is not known. For instance, with a discovery service, a bdev is created when a namespace on a remote NVMeoF target is added, but it's not possible to specify when that happens exactly. Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: I6c1f974fba445376ca9d45aac2639202547410cc Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11960 Community-CI: Mellanox Build Bot Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
parent
c0415feda3
commit
fa649869b9
@ -34,6 +34,11 @@ bdev_crypto_create RPC now requires hexlified 'key' and 'key2' params for all pm
|
||||
Unhexlifying is performed during RPC command processing and the vbdev crypto module runs on
|
||||
binary keys as before.
|
||||
|
||||
### bdev
|
||||
|
||||
Added a timeout option to the `bdev_get_bdevs` RPC. It allows the user to specify the amount of
|
||||
time to wait until a bdev with a given name appears in the system.
|
||||
|
||||
### bdev_nvme
|
||||
|
||||
Added `bdev_nvme_add_error_injection` and `bdev_nvme_remove_error_injection` RPCs to add and
|
||||
|
@ -1607,11 +1607,14 @@ Get information about block devices (bdevs).
|
||||
#### Parameters
|
||||
|
||||
The user may specify no parameters in order to list all block devices, or a block device may be
|
||||
specified by name.
|
||||
specified by name. If a timeout is specified, the method will block until a bdev with a specified
|
||||
name appears or the timeout expires. By default, the timeout is zero, meaning the method returns
|
||||
immediately whether the bdev exists or not.
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Optional | string | Block device name
|
||||
timeout | Optional | number | Time (ms) to wait for a bdev with specified name to appear
|
||||
|
||||
#### Response
|
||||
|
||||
|
@ -441,7 +441,15 @@ rpc_dump_bdev_info(struct spdk_json_write_ctx *w,
|
||||
}
|
||||
|
||||
struct rpc_bdev_get_bdevs {
|
||||
char *name;
|
||||
char *name;
|
||||
uint64_t timeout;
|
||||
};
|
||||
|
||||
struct rpc_bdev_get_bdevs_ctx {
|
||||
struct rpc_bdev_get_bdevs rpc;
|
||||
struct spdk_jsonrpc_request *request;
|
||||
struct spdk_poller *poller;
|
||||
uint64_t timeout_ticks;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -452,13 +460,45 @@ free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r)
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = {
|
||||
{"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true},
|
||||
{"timeout", offsetof(struct rpc_bdev_get_bdevs, timeout), spdk_json_decode_uint64, true},
|
||||
};
|
||||
|
||||
static int
|
||||
get_bdevs_poller(void *_ctx)
|
||||
{
|
||||
struct rpc_bdev_get_bdevs_ctx *ctx = _ctx;
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_bdev *bdev;
|
||||
|
||||
bdev = spdk_bdev_get_by_name(ctx->rpc.name);
|
||||
if (bdev == NULL && spdk_get_ticks() < ctx->timeout_ticks) {
|
||||
return SPDK_POLLER_BUSY;
|
||||
}
|
||||
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("Timed out while waiting for bdev '%s' to appear\n", ctx->rpc.name);
|
||||
spdk_jsonrpc_send_error_response(ctx->request, -ENODEV, spdk_strerror(ENODEV));
|
||||
} else {
|
||||
w = spdk_jsonrpc_begin_result(ctx->request);
|
||||
spdk_json_write_array_begin(w);
|
||||
rpc_dump_bdev_info(w, bdev);
|
||||
spdk_json_write_array_end(w);
|
||||
spdk_jsonrpc_end_result(ctx->request, w);
|
||||
}
|
||||
|
||||
spdk_poller_unregister(&ctx->poller);
|
||||
free_rpc_bdev_get_bdevs(&ctx->rpc);
|
||||
free(ctx);
|
||||
|
||||
return SPDK_POLLER_BUSY;
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_get_bdevs req = {};
|
||||
struct rpc_bdev_get_bdevs_ctx *ctx;
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_bdev *bdev = NULL;
|
||||
|
||||
@ -475,9 +515,34 @@ rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request,
|
||||
if (req.name) {
|
||||
bdev = spdk_bdev_get_by_name(req.name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
free_rpc_bdev_get_bdevs(&req);
|
||||
if (req.timeout == 0) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
free_rpc_bdev_get_bdevs(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
SPDK_ERRLOG("Failed to allocate bdev_get_bdevs context\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
|
||||
free_rpc_bdev_get_bdevs(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->poller = SPDK_POLLER_REGISTER(get_bdevs_poller, ctx, 10 * 1000);
|
||||
if (ctx->poller == NULL) {
|
||||
SPDK_ERRLOG("Failed to register bdev_get_bdevs poller\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
|
||||
free_rpc_bdev_get_bdevs(&req);
|
||||
free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->rpc, &req, sizeof(req));
|
||||
ctx->timeout_ticks = spdk_get_ticks() + req.timeout *
|
||||
spdk_get_ticks_hz() / 1000ull;
|
||||
ctx->request = request;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1003,11 +1003,15 @@ if __name__ == "__main__":
|
||||
|
||||
def bdev_get_bdevs(args):
|
||||
print_dict(rpc.bdev.bdev_get_bdevs(args.client,
|
||||
name=args.name))
|
||||
name=args.name, timeout=args.timeout_ms))
|
||||
|
||||
p = subparsers.add_parser('bdev_get_bdevs', aliases=['get_bdevs'],
|
||||
help='Display current blockdev list or required blockdev')
|
||||
p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False)
|
||||
p.add_argument('-t', '--timeout-ms', help="""Time in ms to wait for the bdev to appear (only used
|
||||
with the -b|--name option). The default timeout is 0, meaning the RPC returns immediately
|
||||
whether the bdev exists or not.""",
|
||||
type=int, required=False)
|
||||
p.set_defaults(func=bdev_get_bdevs)
|
||||
|
||||
def bdev_get_iostat(args):
|
||||
|
@ -1281,11 +1281,12 @@ def bdev_ftl_delete(client, name):
|
||||
|
||||
|
||||
@deprecated_alias('get_bdevs')
|
||||
def bdev_get_bdevs(client, name=None):
|
||||
def bdev_get_bdevs(client, name=None, timeout=None):
|
||||
"""Get information about block devices.
|
||||
|
||||
Args:
|
||||
name: bdev name to query (optional; if omitted, query all bdevs)
|
||||
timeout: time in ms to wait for the bdev with specified name to appear
|
||||
|
||||
Returns:
|
||||
List of bdev information objects.
|
||||
@ -1293,6 +1294,8 @@ def bdev_get_bdevs(client, name=None):
|
||||
params = {}
|
||||
if name:
|
||||
params['name'] = name
|
||||
if timeout:
|
||||
params['timeout'] = timeout
|
||||
return client.call('bdev_get_bdevs', params)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user