diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 7ed77c086..d797dca60 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -10295,6 +10295,43 @@ Example response: } ~~~ +### bdev_raid_grow_base_bdev {#rpc_bdev_raid_grow_base_bdev} + +Add a base bdev to a raid bdev, growing the raid's size if needed + +#### Parameters + +Name | Optional | Type | Description +----------------------- | -------- | ----------- | ----------- +raid_name | Required | string | Raid bdev name +base_name | Required | string | Base bdev name + +#### Example + +Example request: + +~~~json +{ + "jsonrpc": "2.0", + "method": "bdev_raid_grow_base_bdev", + "id": 1, + "params": { + "raid_name": "Raid1", + "base_name": "Nvme1n1", + } +} +~~~ + +Example response: + +~~~json +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + ## SPLIT ### bdev_split_create {#rpc_bdev_split_create} diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index d38dbba20..0064946e1 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -442,3 +442,139 @@ cleanup: free(name); } SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) + +/* + * Input structure for RPC rpc_bdev_raid_grow_base_bdev + */ +struct rpc_bdev_raid_grow_base_bdev { + /* Raid bdev name */ + char *raid_bdev_name; + + /* Base bdev name */ + char *base_bdev_name; +}; + +/* + * brief: + * free_rpc_bdev_raid_grow_base_bdev frees RPC bdev_raid_grow_base_bdev related parameters + * params: + * req - pointer to RPC request + * returns: + * none + */ +static void +free_rpc_bdev_raid_grow_base_bdev(struct rpc_bdev_raid_grow_base_bdev *req) +{ + free(req->raid_bdev_name); + free(req->base_bdev_name); +} + +/* + * Decoder object for RPC bdev_raid_grow_base_bdev + */ +static const struct spdk_json_object_decoder rpc_bdev_raid_grow_base_bdev_decoders[] = { + {"raid_name", offsetof(struct rpc_bdev_raid_grow_base_bdev, raid_bdev_name), spdk_json_decode_string}, + {"base_name", offsetof(struct rpc_bdev_raid_grow_base_bdev, base_bdev_name), spdk_json_decode_string}, +}; + +struct rpc_bdev_raid_grow_base_bdev_ctx { + struct rpc_bdev_raid_grow_base_bdev req; + struct spdk_jsonrpc_request *request; +}; + +/* + * brief: + * params: + * cb_arg - pointer to the callback context. + * rc - return code of the adding a base bdev. + * returns: + * none + */ +static void +bdev_raid_grow_base_bdev_done(void *cb_arg, int rc) +{ + struct rpc_bdev_raid_grow_base_bdev_ctx *ctx = cb_arg; + struct spdk_jsonrpc_request *request = ctx->request; + + if (rc != 0) { + SPDK_ERRLOG("Failed to grow raid %s adding base bdev %s (%d): %s\n", + ctx->req.raid_bdev_name, ctx->req.base_bdev_name, rc, spdk_strerror(-rc)); + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + spdk_strerror(-rc)); + goto exit; + } + + spdk_jsonrpc_send_bool_response(request, true); +exit: + free_rpc_bdev_raid_grow_base_bdev(&ctx->req); + free(ctx); +} + +/* + * brief: + * bdev_raid_grow_base_bdev is the RPC add a base bdev to a raid bdev, growing the raid's size if needed + * It takes raid bdev name and base bdev name as input. + * params: + * request - pointer to json rpc request + * params - pointer to request parameters + * returns: + * none + */ +static void +rpc_bdev_raid_grow_base_bdev(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_bdev_raid_grow_base_bdev_ctx *ctx; + struct raid_bdev *raid_bdev; + struct spdk_bdev *base_bdev; + int rc; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); + return; + } + + if (spdk_json_decode_object(params, rpc_bdev_raid_grow_base_bdev_decoders, + SPDK_COUNTOF(rpc_bdev_raid_grow_base_bdev_decoders), + &ctx->req)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, + "spdk_json_decode_object failed"); + goto cleanup; + } + + raid_bdev = raid_bdev_find_by_name(ctx->req.raid_bdev_name); + if (raid_bdev == NULL) { + spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, + "raid bdev %s not found", + ctx->req.raid_bdev_name); + goto cleanup; + } + + base_bdev = spdk_bdev_get_by_name(ctx->req.base_bdev_name); + if (base_bdev == NULL) { + spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, + "base bdev %s not found", + ctx->req.base_bdev_name); + goto cleanup; + } + + ctx->request = request; + + rc = raid_bdev_grow_base_bdev(raid_bdev, ctx->req.base_bdev_name, bdev_raid_grow_base_bdev_done, + ctx); + if (rc != 0) { + spdk_jsonrpc_send_error_response_fmt(request, rc, + "Failed to grow raid %s adding base bdev %s: %s", + ctx->req.raid_bdev_name, ctx->req.base_bdev_name, + spdk_strerror(-rc)); + goto cleanup; + } + + return; + +cleanup: + free_rpc_bdev_raid_grow_base_bdev(&ctx->req); + free(ctx); +} +SPDK_RPC_REGISTER("bdev_raid_grow_base_bdev", rpc_bdev_raid_grow_base_bdev, SPDK_RPC_RUNTIME) diff --git a/python/spdk/rpc/bdev.py b/python/spdk/rpc/bdev.py index 6206f497c..203905ce5 100644 --- a/python/spdk/rpc/bdev.py +++ b/python/spdk/rpc/bdev.py @@ -457,6 +457,21 @@ def bdev_raid_remove_base_bdev(client, name): return client.call('bdev_raid_remove_base_bdev', params) +def bdev_raid_grow_base_bdev(client, raid_name, base_name): + """Add a base bdev to a raid bdev, growing the raid's size if needed + + Args: + raid_name: raid bdev name + base_name: base bdev name + + Returns: + None + """ + params = {'raid_name': raid_name, 'base_name': base_name} + + return client.call('bdev_raid_grow_base_bdev', params) + + def bdev_aio_create(client, filename, name, block_size=None, readonly=False): """Construct a Linux AIO block device. diff --git a/scripts/rpc.py b/scripts/rpc.py index a9db05f8c..9484abaf8 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2138,6 +2138,16 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.add_argument('name', help='base bdev name') p.set_defaults(func=bdev_raid_remove_base_bdev) + def bdev_raid_grow_base_bdev(args): + rpc.bdev.bdev_raid_grow_base_bdev(args.client, + raid_name=args.raid_name, + base_name=args.base_name) + p = subparsers.add_parser('bdev_raid_grow_base_bdev', help="""Add a base bdev to a raid bdev, + growing the raid\'s size if needed""") + p.add_argument('raid_name', help='raid bdev name') + p.add_argument('base_name', help='base bdev name') + p.set_defaults(func=bdev_raid_grow_base_bdev) + # split def bdev_split_create(args): print_array(rpc.bdev.bdev_split_create(args.client,