bdev/rbd: add ceph rbd resize function

This is to backport below change to SPDK v20.01.2 LTS release.
6a29c6a906

Change-Id: I9b7ed97f2a376af71578ccb5556231832863b255
Signed-off-by: Liang Yan <liang.z.yan@intel.com>
Signed-off-by: GangCao <gang.cao@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2262
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
GangCao 2020-05-07 14:25:21 -04:00 committed by Tomasz Zawadzki
parent d4d3e76aed
commit a7f7b1955e
9 changed files with 187 additions and 0 deletions

View File

@ -153,6 +153,8 @@ A new RPC, `framework_get_reactors`, has been added to retrieve a list of all re
`nvmf_set_config` now takes an argument to enable passthru of identify commands to base NVMe devices. `nvmf_set_config` now takes an argument to enable passthru of identify commands to base NVMe devices.
Please see the nvmf section above for more details. Please see the nvmf section above for more details.
A new RPC, `bdev_rbd_resize` has been added to resize the Ceph RBD bdev.
### scsi ### scsi
`spdk_scsi_lun_get_dif_ctx` now takes an additional argument of type `spdk_scsi_task`. `spdk_scsi_lun_get_dif_ctx` now takes an additional argument of type `spdk_scsi_task`.

View File

@ -119,6 +119,12 @@ To remove a block device representation use the bdev_rbd_delete command.
`rpc.py bdev_rbd_delete Rbd0` `rpc.py bdev_rbd_delete Rbd0`
To resize a bdev use the bdev_rbd_resize command.
`rpc.py bdev_rbd_resize Rbd0 4096`
This command will resize the Rbd0 bdev to 4096 MiB.
# Compression Virtual Bdev Module {#bdev_config_compress} # Compression Virtual Bdev Module {#bdev_config_compress}
The compression bdev module can be configured to provide compression/decompression The compression bdev module can be configured to provide compression/decompression

View File

@ -1853,6 +1853,49 @@ Example response:
} }
~~~ ~~~
## bdev_rbd_resize {#rpc_bdev_rbd_resize}
Resize @ref bdev_config_rbd bdev
This method is available only if SPDK was build with Ceph RBD support.
### Result
`true` if bdev with provided name was resized or `false` otherwise.
### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
name | Required | string | Bdev name
new_size | Required | int | New bdev size for resize operation in MiB
### Example
Example request:
~~~
{
"params": {
"name": "Rbd0"
"new_size": "4096"
},
"jsonrpc": "2.0",
"method": "bdev_rbd_resize",
"id": 1
}
~~~
Example response:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
~~~
## bdev_delay_create {#rpc_bdev_delay_create} ## bdev_delay_create {#rpc_bdev_delay_create}
Create delay bdev. This bdev type redirects all IO to it's base bdev and inserts a delay on the completion Create delay bdev. This bdev type redirects all IO to it's base bdev and inserts a delay on the completion

View File

@ -783,6 +783,44 @@ spdk_bdev_rbd_delete(struct spdk_bdev *bdev, spdk_delete_rbd_complete cb_fn, voi
spdk_bdev_unregister(bdev, cb_fn, cb_arg); spdk_bdev_unregister(bdev, cb_fn, cb_arg);
} }
int
spdk_bdev_rbd_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_mb)
{
struct spdk_io_channel *ch;
struct bdev_rbd_io_channel *rbd_io_ch;
int rc;
uint64_t new_size_in_byte;
uint64_t current_size_in_mb;
if (bdev->module != &rbd_if) {
return -EINVAL;
}
current_size_in_mb = bdev->blocklen * bdev->blockcnt / (1024 * 1024);
if (current_size_in_mb > new_size_in_mb) {
SPDK_ERRLOG("The new bdev size must be lager than current bdev size.\n");
return -EINVAL;
}
ch = bdev_rbd_get_io_channel(bdev);
rbd_io_ch = spdk_io_channel_get_ctx(ch);
new_size_in_byte = new_size_in_mb * 1024 * 1024;
rc = rbd_resize(rbd_io_ch->image, new_size_in_byte);
if (rc != 0) {
SPDK_ERRLOG("failed to resize the ceph bdev.\n");
return rc;
}
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 rc;
}
static int static int
bdev_rbd_library_init(void) bdev_rbd_library_init(void)
{ {

View File

@ -57,4 +57,12 @@ int spdk_bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *
void spdk_bdev_rbd_delete(struct spdk_bdev *bdev, spdk_delete_rbd_complete cb_fn, void spdk_bdev_rbd_delete(struct spdk_bdev *bdev, spdk_delete_rbd_complete cb_fn,
void *cb_arg); void *cb_arg);
/**
* Resize rbd bdev.
*
* \param bdev Pointer to rbd bdev.
* \param new_size_in_mb The new size in MiB for this bdev.
*/
int spdk_bdev_rbd_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_mb);
#endif /* SPDK_BDEV_RBD_H */ #endif /* SPDK_BDEV_RBD_H */

View File

@ -197,3 +197,56 @@ cleanup:
} }
SPDK_RPC_REGISTER("bdev_rbd_delete", spdk_rpc_bdev_rbd_delete, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER("bdev_rbd_delete", spdk_rpc_bdev_rbd_delete, SPDK_RPC_RUNTIME)
SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_rbd_delete, delete_rbd_bdev) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_rbd_delete, delete_rbd_bdev)
struct rpc_bdev_rbd_resize {
char *name;
uint64_t new_size;
};
static const struct spdk_json_object_decoder rpc_bdev_rbd_resize_decoders[] = {
{"name", offsetof(struct rpc_bdev_rbd_resize, name), spdk_json_decode_string},
{"new_size", offsetof(struct rpc_bdev_rbd_resize, new_size), spdk_json_decode_uint64}
};
static void
free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req)
{
free(req->name);
}
static void
spdk_rpc_bdev_rbd_resize(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_rbd_resize req = {};
struct spdk_bdev *bdev;
struct spdk_json_write_ctx *w;
int rc;
if (spdk_json_decode_object(params, rpc_bdev_rbd_resize_decoders,
SPDK_COUNTOF(rpc_bdev_rbd_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 = spdk_bdev_rbd_resize(bdev, req.new_size);
if (rc) {
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
goto cleanup;
}
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
cleanup:
free_rpc_bdev_rbd_resize(&req);
}
SPDK_RPC_REGISTER("bdev_rbd_resize", spdk_rpc_bdev_rbd_resize, SPDK_RPC_RUNTIME)

View File

@ -541,6 +541,20 @@ if __name__ == "__main__":
p.add_argument('name', help='rbd bdev name') p.add_argument('name', help='rbd bdev name')
p.set_defaults(func=bdev_rbd_delete) p.set_defaults(func=bdev_rbd_delete)
def bdev_rbd_resize(args):
print_json(rpc.bdev.bdev_rbd_resize(args.client,
name=args.name,
new_size=int(args.new_size)))
rpc.bdev.bdev_rbd_resize(args.client,
name=args.name,
new_size=int(args.new_size))
p = subparsers.add_parser('bdev_rbd_resize',
help='Resize a rbd bdev')
p.add_argument('name', help='rbd bdev name')
p.add_argument('new_size', help='new bdev size for resize operation. The unit is MiB')
p.set_defaults(func=bdev_rbd_resize)
def bdev_delay_create(args): def bdev_delay_create(args):
print_json(rpc.bdev.bdev_delay_create(args.client, print_json(rpc.bdev.bdev_delay_create(args.client,
base_bdev_name=args.base_bdev_name, base_bdev_name=args.base_bdev_name,

View File

@ -585,6 +585,20 @@ def bdev_rbd_delete(client, name):
return client.call('bdev_rbd_delete', params) return client.call('bdev_rbd_delete', params)
def bdev_rbd_resize(client, name, new_size):
"""Resize rbd bdev in the system.
Args:
name: name of rbd 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_rbd_resize', params)
@deprecated_alias('construct_error_bdev') @deprecated_alias('construct_error_bdev')
def bdev_error_create(client, base_name): def bdev_error_create(client, base_name):
"""Construct an error injection block device. """Construct an error injection block device.

View File

@ -40,6 +40,15 @@ $rpc_py iscsi_create_portal_group $PORTAL_TAG $TARGET_IP:$ISCSI_PORT
$rpc_py iscsi_create_initiator_group $INITIATOR_TAG $INITIATOR_NAME $NETMASK $rpc_py iscsi_create_initiator_group $INITIATOR_TAG $INITIATOR_NAME $NETMASK
rbd_bdev="$($rpc_py bdev_rbd_create $RBD_POOL $RBD_NAME 4096)" rbd_bdev="$($rpc_py bdev_rbd_create $RBD_POOL $RBD_NAME 4096)"
$rpc_py bdev_get_bdevs $rpc_py bdev_get_bdevs
$rpc_py bdev_rbd_resize $rbd_bdev 2000
num_block=$($rpc_py bdev_get_bdevs|grep num_blocks|sed 's/[^[:digit:]]//g')
# get the bdev size in MiB.
total_size=$(( num_block * 4096/ 1048576 ))
if [ $total_size != 2000 ];then
echo "resize failed."
exit 1
fi
# "Ceph0:0" ==> use Ceph0 blockdev for LUN0 # "Ceph0:0" ==> use Ceph0 blockdev for LUN0
# "1:2" ==> map PortalGroup1 to InitiatorGroup2 # "1:2" ==> map PortalGroup1 to InitiatorGroup2
# "64" ==> iSCSI queue depth 64 # "64" ==> iSCSI queue depth 64