diff --git a/lib/bdev/pmem/bdev_pmem_rpc.c b/lib/bdev/pmem/bdev_pmem_rpc.c index 8e2a00c32..058c29ab0 100644 --- a/lib/bdev/pmem/bdev_pmem_rpc.c +++ b/lib/bdev/pmem/bdev_pmem_rpc.c @@ -99,3 +99,193 @@ invalid: free_rpc_construct_pmem_bdev(&req); } SPDK_RPC_REGISTER("construct_pmem_bdev", spdk_rpc_construct_pmem_bdev) + +struct rpc_create_pmem_pool { + char *pmem_file; + uint64_t num_blocks; + uint32_t block_size; +}; + +static const struct spdk_json_object_decoder rpc_create_pmem_pool_decoders[] = { + {"pmem_file", offsetof(struct rpc_create_pmem_pool, pmem_file), spdk_json_decode_string}, + {"num_blocks", offsetof(struct rpc_create_pmem_pool, num_blocks), spdk_json_decode_uint64}, + {"block_size", offsetof(struct rpc_create_pmem_pool, block_size), spdk_json_decode_uint32}, +}; + +static void +free_rpc_create_pmem_pool(struct rpc_create_pmem_pool *req) +{ + free(req->pmem_file); +} + +static void +spdk_rpc_create_pmem_pool(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_create_pmem_pool req = {}; + struct spdk_json_write_ctx *w; + uint64_t pool_size; + PMEMblkpool *pbp; + + if (spdk_json_decode_object(params, rpc_create_pmem_pool_decoders, + SPDK_COUNTOF(rpc_create_pmem_pool_decoders), + &req)) { + SPDK_DEBUGLOG(SPDK_TRACE_BDEV_PMEM, "spdk_json_decode_object failed\n"); + goto invalid; + } + + /* libpmemblk pool has to contain at least 256 blocks */ + if (req.num_blocks < 256) { + goto invalid; + } + + pool_size = req.num_blocks * req.block_size; + if (pool_size < PMEMBLK_MIN_POOL) { + goto invalid; + } + + pbp = pmemblk_create(req.pmem_file, req.block_size, pool_size, 0666); + if (pbp == NULL) { + goto invalid; + } + + pmemblk_close(pbp); + + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + free_rpc_create_pmem_pool(&req); + return; + } + + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + free_rpc_create_pmem_pool(&req); + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + free_rpc_create_pmem_pool(&req); +} +SPDK_RPC_REGISTER("create_pmem_pool", spdk_rpc_create_pmem_pool) + +struct rpc_pmem_pool_info { + char *pmem_file; +}; + +static const struct spdk_json_object_decoder rpc_pmem_pool_info_decoders[] = { + {"pmem_file", offsetof(struct rpc_pmem_pool_info, pmem_file), spdk_json_decode_string}, +}; + +static void +free_rpc_pmem_pool_info(struct rpc_pmem_pool_info *req) +{ + free(req->pmem_file); +} + +static void +spdk_rpc_pmem_pool_info(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_pmem_pool_info req = {}; + struct spdk_json_write_ctx *w; + size_t num_blocks, block_size; + PMEMblkpool *pbp; + + if (spdk_json_decode_object(params, rpc_pmem_pool_info_decoders, + SPDK_COUNTOF(rpc_pmem_pool_info_decoders), + &req)) { + SPDK_DEBUGLOG(SPDK_TRACE_BDEV_PMEM, "spdk_json_decode_object failed\n"); + goto invalid; + } + + pbp = pmemblk_open(req.pmem_file, 0); + if (pbp == NULL) { + goto invalid; + } + + block_size = pmemblk_bsize(pbp); + num_blocks = pmemblk_nblock(pbp); + + + pmemblk_close(pbp); + + /* Check pmem pool consistency */ + if (pmemblk_check(req.pmem_file, block_size) != 1) { + goto invalid; + } + + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + free_rpc_pmem_pool_info(&req); + return; + } + + spdk_json_write_array_begin(w); + spdk_json_write_object_begin(w); + spdk_json_write_name(w, "num_blocks"); + spdk_json_write_uint64(w, num_blocks); + spdk_json_write_name(w, "block_size"); + spdk_json_write_uint64(w, block_size); + spdk_json_write_object_end(w); + spdk_json_write_array_end(w); + spdk_jsonrpc_end_result(request, w); + free_rpc_pmem_pool_info(&req); + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + free_rpc_pmem_pool_info(&req); +} +SPDK_RPC_REGISTER("pmem_pool_info", spdk_rpc_pmem_pool_info) + +struct rpc_delete_pmem_pool { + char *pmem_file; +}; + +static const struct spdk_json_object_decoder rpc_delete_pmem_pool_decoders[] = { + {"pmem_file", offsetof(struct rpc_delete_pmem_pool, pmem_file), spdk_json_decode_string}, +}; + +static void +free_rpc_delete_pmem_pool(struct rpc_delete_pmem_pool *req) +{ + free(req->pmem_file); +} + +static void +spdk_rpc_delete_pmem_pool(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_delete_pmem_pool req = {}; + struct spdk_json_write_ctx *w; + + if (spdk_json_decode_object(params, rpc_delete_pmem_pool_decoders, + SPDK_COUNTOF(rpc_delete_pmem_pool_decoders), + &req)) { + SPDK_DEBUGLOG(SPDK_TRACE_BDEV_PMEM, "spdk_json_decode_object failed\n"); + goto invalid; + } + + /* Check if file is actually pmem pool */ + if (pmemblk_check(req.pmem_file, 0) != 1) { + goto invalid; + } + + unlink(req.pmem_file); + + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + free_rpc_delete_pmem_pool(&req); + return; + } + + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + free_rpc_delete_pmem_pool(&req); + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + free_rpc_delete_pmem_pool(&req); +} +SPDK_RPC_REGISTER("delete_pmem_pool", spdk_rpc_delete_pmem_pool) diff --git a/scripts/rpc.py b/scripts/rpc.py index 7f1fe2c58..8b304adb0 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -177,6 +177,38 @@ p.add_argument('block_size', help='Block size for this bdev', type=int) p.set_defaults(func=construct_malloc_bdev) +def create_pmem_pool(args): + num_blocks = (args.total_size * 1024 * 1024) / args.block_size + params = {'pmem_file': args.pmem_file, + 'num_blocks': num_blocks, + 'block_size': args.block_size} + jsonrpc_call('create_pmem_pool', params) + +p = subparsers.add_parser('create_pmem_pool', help='Create pmem pool') +p.add_argument('pmem_file', help='Path to pmemblk pool file') +p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) +p.add_argument('block_size', help='Block size for this pmem pool', type=int) +p.set_defaults(func=create_pmem_pool) + + +def pmem_pool_info(args): + params = {'pmem_file': args.pmem_file} + print_dict(jsonrpc_call('pmem_pool_info', params)) + +p = subparsers.add_parser('pmem_pool_info', help='Display pmem pool info and check consistency') +p.add_argument('pmem_file', help='Path to pmemblk pool file') +p.set_defaults(func=pmem_pool_info) + + +def delete_pmem_pool(args): + params = {'pmem_file': args.pmem_file} + jsonrpc_call('delete_pmem_pool', params) + +p = subparsers.add_parser('delete_pmem_pool', help='Delete pmem pool') +p.add_argument('pmem_file', help='Path to pmemblk pool file') +p.set_defaults(func=delete_pmem_pool) + + def construct_pmem_bdev(args): params = {'pmem_file': args.pmem_file} print_array(jsonrpc_call('construct_pmem_bdev', params))