diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index df5a4e245..030c7cc5b 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -2268,6 +2268,43 @@ Example response: } ~~~ +## bdev_null_resize {#rpc_bdev_null_resize} + +Resize @ref bdev_config_null. + +### Parameters + +Name | Optional | Type | Description +----------------------- | -------- | ----------- | ----------- +name | Required | string | Bdev name +new_size | Required | number | Bdev new capacity in MB + +### Example + +Example request: + +~~~ +{ + "params": { + "name": "Null0", + "new_size": 4096 + }, + "jsonrpc": "2.0", + "method": "bdev_null_resize", + "id": 1 +} +~~~ + +Example response: + +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + ## bdev_aio_create {#rpc_bdev_aio_create} Construct @ref bdev_config_aio. diff --git a/module/bdev/null/bdev_null.c b/module/bdev/null/bdev_null.c index 0c4202e4f..a0e67ee00 100644 --- a/module/bdev/null/bdev_null.c +++ b/module/bdev/null/bdev_null.c @@ -420,6 +420,34 @@ bdev_null_initialize(void) return 0; } +int +bdev_null_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_mb) +{ + uint64_t current_size_in_mb; + uint64_t new_size_in_byte; + int rc; + + if (bdev->module != &null_if) { + return -EINVAL; + } + + current_size_in_mb = bdev->blocklen * bdev->blockcnt / (1024 * 1024); + if (new_size_in_mb < current_size_in_mb) { + SPDK_ERRLOG("The new bdev size must not be smaller than current bdev size.\n"); + return -EINVAL; + } + + new_size_in_byte = new_size_in_mb * 1024 * 1024; + + rc = spdk_bdev_notify_blockcnt_change(bdev, new_size_in_byte / bdev->blocklen); + if (rc != 0) { + SPDK_ERRLOG("failed to notify block cnt change.\n"); + return rc; + } + + return 0; +} + static void _bdev_null_finish_cb(void *arg) { diff --git a/module/bdev/null/bdev_null.h b/module/bdev/null/bdev_null.h index 07db54e48..c9d4ac704 100644 --- a/module/bdev/null/bdev_null.h +++ b/module/bdev/null/bdev_null.h @@ -63,5 +63,12 @@ int bdev_null_create(struct spdk_bdev **bdev, const struct spdk_null_bdev_opts * */ void bdev_null_delete(struct spdk_bdev *bdev, spdk_delete_null_complete cb_fn, void *cb_arg); +/** + * Resize null bdev. + * + * \param bdev Pointer to null bdev. + * \param new_size_in_mb The new size in MiB for this bdev + */ +int bdev_null_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_mb); #endif /* SPDK_BDEV_NULL_H */ diff --git a/module/bdev/null/bdev_null_rpc.c b/module/bdev/null/bdev_null_rpc.c index 4dd521e14..b20469378 100644 --- a/module/bdev/null/bdev_null_rpc.c +++ b/module/bdev/null/bdev_null_rpc.c @@ -206,3 +206,53 @@ cleanup: } SPDK_RPC_REGISTER("bdev_null_delete", rpc_bdev_null_delete, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_null_delete, delete_null_bdev) + +struct rpc_bdev_null_resize { + char *name; + uint64_t new_size; +}; + +static const struct spdk_json_object_decoder rpc_bdev_null_resize_decoders[] = { + {"name", offsetof(struct rpc_bdev_null_resize, name), spdk_json_decode_string}, + {"new_size", offsetof(struct rpc_bdev_null_resize, new_size), spdk_json_decode_uint64} +}; + +static void +free_rpc_bdev_null_resize(struct rpc_bdev_null_resize *req) +{ + free(req->name); +} + +static void +spdk_rpc_bdev_null_resize(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_bdev_null_resize req = {}; + struct spdk_bdev *bdev; + int rc; + + if (spdk_json_decode_object(params, rpc_bdev_null_resize_decoders, + SPDK_COUNTOF(rpc_bdev_null_resize_decoders), + &req)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "spdk_json_decode_object failed"); + goto cleanup; + } + + bdev = spdk_bdev_get_by_name(req.name); + if (bdev == NULL) { + spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); + goto cleanup; + } + + rc = bdev_null_resize(bdev, req.new_size); + if (rc) { + spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); + goto cleanup; + } + + spdk_jsonrpc_send_bool_response(request, true); +cleanup: + free_rpc_bdev_null_resize(&req); +} +SPDK_RPC_REGISTER("bdev_null_resize", spdk_rpc_bdev_null_resize, SPDK_RPC_RUNTIME) diff --git a/scripts/rpc.py b/scripts/rpc.py index 313eaad15..685b07468 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -382,6 +382,17 @@ if __name__ == "__main__": p.add_argument('name', help='null bdev name') p.set_defaults(func=bdev_null_delete) + def bdev_null_resize(args): + print_json(rpc.bdev.bdev_null_resize(args.client, + name=args.name, + new_size=int(args.new_size))) + + p = subparsers.add_parser('bdev_null_resize', + help='Resize a null bdev') + p.add_argument('name', help='null bdev name') + p.add_argument('new_size', help='new bdev size for resize operation. The unit is MiB') + p.set_defaults(func=bdev_null_resize) + def bdev_aio_create(args): print_json(rpc.bdev.bdev_aio_create(args.client, filename=args.filename, diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 4dd05377e..fcd0129e2 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -277,6 +277,20 @@ def bdev_null_delete(client, name): return client.call('bdev_null_delete', params) +def bdev_null_resize(client, name, new_size): + """Resize null bdev in the system. + + Args: + name: name of null bdev to resize + new_size: new bdev size of resize operation. The unit is MiB + """ + params = { + 'name': name, + 'new_size': new_size, + } + return client.call('bdev_null_resize', params) + + @deprecated_alias('get_raid_bdevs') def bdev_raid_get_bdevs(client, category): """Get list of raid bdevs based on category