diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bb1c6815..8776cc0f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ is fabric or not. API `spdk_nvme_poll_group_remove` was limited to be available only for a disconnected qpair in the group. +### bdev_aio + +Added `bdev_aio_rescan` RPC to allow rescaning the size of aio bdev + ### bdev The NVMe bdev module supports multipath and improved I/O error resiliency. diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 282c693d2..80ccfdfdb 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -2813,6 +2813,41 @@ Example response: } ~~~ +### bdev_aio_rescan {#rpc_bdev_aio_rescan} + +Rescan the size of @ref bdev_config_aio. + +#### Parameters + +Name | Optional | Type | Description +----------------------- | -------- | ----------- | ----------- +name | Required | string | Bdev name + +#### Example + +Example request: + +~~json +{ + "params": { + "name": "Aio0" + }, + "jsonrpc": "2.0", + "method": "bdev_aio_rescan", + "id": 1 +} +~~ + +Example response: + +~~json +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~ + ### bdev_aio_delete {#rpc_bdev_aio_delete} Delete @ref bdev_config_aio. diff --git a/module/bdev/aio/bdev_aio.c b/module/bdev/aio/bdev_aio.c index 8c8c93cb6..e81c2522d 100644 --- a/module/bdev/aio/bdev_aio.c +++ b/module/bdev/aio/bdev_aio.c @@ -820,6 +820,38 @@ error_return: return rc; } +int +bdev_aio_rescan(struct spdk_bdev *bdev) +{ + struct file_disk *fdisk; + uint64_t disk_size, blockcnt; + int rc; + + if (!bdev || bdev->module != &aio_if) { + return -ENODEV; + } + + fdisk = SPDK_CONTAINEROF(bdev, struct file_disk, disk); + disk_size = spdk_fd_get_size(fdisk->fd); + blockcnt = disk_size / fdisk->disk.blocklen; + + if (fdisk->disk.blockcnt != blockcnt) { + SPDK_NOTICELOG("AIO device is resized: bdev name %s, old block count %" PRIu64 ", new block count %" + PRIu64 "\n", + fdisk->filename, + fdisk->disk.blockcnt, + blockcnt); + rc = spdk_bdev_notify_blockcnt_change(&fdisk->disk, blockcnt); + if (rc != 0) { + SPDK_ERRLOG("Could not change num blocks for aio bdev: name %s, errno: %d.\n", + fdisk->filename, rc); + return rc; + } + } + + return 0; +} + struct delete_aio_bdev_ctx { delete_aio_bdev_complete cb_fn; void *cb_arg; diff --git a/module/bdev/aio/bdev_aio.h b/module/bdev/aio/bdev_aio.h index 9ba425946..563aeb063 100644 --- a/module/bdev/aio/bdev_aio.h +++ b/module/bdev/aio/bdev_aio.h @@ -41,6 +41,7 @@ typedef void (*delete_aio_bdev_complete)(void *cb_arg, int bdeverrno); int create_aio_bdev(const char *name, const char *filename, uint32_t block_size); +int bdev_aio_rescan(struct spdk_bdev *bdev); void bdev_aio_delete(struct spdk_bdev *bdev, delete_aio_bdev_complete cb_fn, void *cb_arg); #endif /* SPDK_BDEV_AIO_H */ diff --git a/module/bdev/aio/bdev_aio_rpc.c b/module/bdev/aio/bdev_aio_rpc.c index da625c8fe..7bab2c0a4 100644 --- a/module/bdev/aio/bdev_aio_rpc.c +++ b/module/bdev/aio/bdev_aio_rpc.c @@ -111,6 +111,44 @@ rpc_bdev_aio_create(struct spdk_jsonrpc_request *request, SPDK_RPC_REGISTER("bdev_aio_create", rpc_bdev_aio_create, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_aio_create, construct_aio_bdev) +struct rpc_rescan_aio { + char *name; +}; + +static const struct spdk_json_object_decoder rpc_rescan_aio_decoders[] = { + {"name", offsetof(struct rpc_rescan_aio, name), spdk_json_decode_string}, +}; + +static void +rpc_bdev_aio_rescan(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_rescan_aio req = {NULL}; + struct spdk_bdev *bdev; + int bdeverrno; + + if (spdk_json_decode_object(params, rpc_rescan_aio_decoders, + SPDK_COUNTOF(rpc_rescan_aio_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; + } + + bdeverrno = bdev_aio_rescan(bdev); + spdk_jsonrpc_send_bool_response(request, bdeverrno); + +cleanup: + free(req.name); +} +SPDK_RPC_REGISTER("bdev_aio_rescan", rpc_bdev_aio_rescan, SPDK_RPC_RUNTIME) + struct rpc_delete_aio { char *name; }; diff --git a/scripts/rpc.py b/scripts/rpc.py index c1939e5ea..ee760ab05 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -426,6 +426,14 @@ if __name__ == "__main__": p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?', default=0) p.set_defaults(func=bdev_aio_create) + def bdev_aio_rescan(args): + print_json(rpc.bdev.bdev_aio_rescan(args.client, + name=args.name)) + + p = subparsers.add_parser('bdev_aio_rescan', help='Rescan a bdev size with aio backend') + p.add_argument('name', help='Block device name') + p.set_defaults(func=bdev_aio_rescan) + def bdev_aio_delete(args): rpc.bdev.bdev_aio_delete(args.client, name=args.name) diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 97d036287..636126c58 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -386,6 +386,16 @@ def bdev_aio_create(client, filename, name, block_size=None): return client.call('bdev_aio_create', params) +def bdev_aio_rescan(client, name): + """Rescan a Linux AIO block device. + + Args: + bdev_name: name of aio bdev to delete + """ + params = {'name': name} + return client.call('bdev_aio_rescan', params) + + @deprecated_alias('delete_aio_bdev') def bdev_aio_delete(client, name): """Remove aio bdev from the system.