diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 2e272fec97..997b42fa77 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -2496,6 +2496,7 @@ name | Optional | string | Bdev name to use block_size | Required | number | Block size in bytes -must be multiple of 512 num_blocks | Required | number | Number of blocks uuid | Optional | string | UUID of new bdev +optimal_io_boundary | Optional | number | Split on optimal IO boundary, in number of blocks, default 0 #### Result @@ -2511,7 +2512,8 @@ Example request: "block_size": 4096, "num_blocks": 16384, "name": "Malloc0", - "uuid": "2b6601ba-eada-44fb-9a83-a20eb9eb9e90" + "uuid": "2b6601ba-eada-44fb-9a83-a20eb9eb9e90", + "optimal_io_boundary": 16 }, "jsonrpc": "2.0", "method": "bdev_malloc_create", diff --git a/module/bdev/malloc/bdev_malloc.c b/module/bdev/malloc/bdev_malloc.c index 3f5f65e59d..4f90243107 100644 --- a/module/bdev/malloc/bdev_malloc.c +++ b/module/bdev/malloc/bdev_malloc.c @@ -3,6 +3,7 @@ * * Copyright (c) Intel Corporation. * All rights reserved. + * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -361,6 +362,7 @@ bdev_malloc_write_json_config(struct spdk_bdev *bdev, struct spdk_json_write_ctx spdk_json_write_named_uint32(w, "block_size", bdev->blocklen); spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); spdk_json_write_named_string(w, "uuid", uuid_str); + spdk_json_write_named_uint32(w, "optimal_io_boundary", bdev->optimal_io_boundary); spdk_json_write_object_end(w); @@ -377,7 +379,7 @@ static const struct spdk_bdev_fn_table malloc_fn_table = { int create_malloc_disk(struct spdk_bdev **bdev, const char *name, const struct spdk_uuid *uuid, - uint64_t num_blocks, uint32_t block_size) + uint64_t num_blocks, uint32_t block_size, uint32_t optimal_io_boundary) { struct malloc_disk *mdisk; int rc; @@ -428,6 +430,10 @@ create_malloc_disk(struct spdk_bdev **bdev, const char *name, const struct spdk_ mdisk->disk.write_cache = 1; mdisk->disk.blocklen = block_size; mdisk->disk.blockcnt = num_blocks; + if (optimal_io_boundary) { + mdisk->disk.optimal_io_boundary = optimal_io_boundary; + mdisk->disk.split_on_optimal_io_boundary = true; + } if (uuid) { mdisk->disk.uuid = *uuid; } else { diff --git a/module/bdev/malloc/bdev_malloc.h b/module/bdev/malloc/bdev_malloc.h index b683b10628..054cf3e3c5 100644 --- a/module/bdev/malloc/bdev_malloc.h +++ b/module/bdev/malloc/bdev_malloc.h @@ -3,6 +3,7 @@ * * Copyright (c) Intel Corporation. * All rights reserved. + * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,7 +42,7 @@ typedef void (*spdk_delete_malloc_complete)(void *cb_arg, int bdeverrno); int create_malloc_disk(struct spdk_bdev **bdev, const char *name, const struct spdk_uuid *uuid, - uint64_t num_blocks, uint32_t block_size); + uint64_t num_blocks, uint32_t block_size, uint32_t optimal_io_boundary); void delete_malloc_disk(struct spdk_bdev *bdev, spdk_delete_malloc_complete cb_fn, void *cb_arg); diff --git a/module/bdev/malloc/bdev_malloc_rpc.c b/module/bdev/malloc/bdev_malloc_rpc.c index 940f9ca114..bfa1e7d1b4 100644 --- a/module/bdev/malloc/bdev_malloc_rpc.c +++ b/module/bdev/malloc/bdev_malloc_rpc.c @@ -3,6 +3,7 @@ * * Copyright (c) Intel Corporation. * All rights reserved. + * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,6 +44,7 @@ struct rpc_construct_malloc { char *uuid; uint64_t num_blocks; uint32_t block_size; + uint32_t optimal_io_boundary; }; static void @@ -57,6 +59,7 @@ static const struct spdk_json_object_decoder rpc_construct_malloc_decoders[] = { {"uuid", offsetof(struct rpc_construct_malloc, uuid), spdk_json_decode_string, true}, {"num_blocks", offsetof(struct rpc_construct_malloc, num_blocks), spdk_json_decode_uint64}, {"block_size", offsetof(struct rpc_construct_malloc, block_size), spdk_json_decode_uint32}, + {"optimal_io_boundary", offsetof(struct rpc_construct_malloc, optimal_io_boundary), spdk_json_decode_uint32, true}, }; static void @@ -94,7 +97,8 @@ rpc_bdev_malloc_create(struct spdk_jsonrpc_request *request, uuid = &decoded_uuid; } - rc = create_malloc_disk(&bdev, req.name, uuid, req.num_blocks, req.block_size); + rc = create_malloc_disk(&bdev, req.name, uuid, req.num_blocks, req.block_size, + req.optimal_io_boundary); if (rc) { spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); goto cleanup; diff --git a/scripts/rpc.py b/scripts/rpc.py index 09a8a51753..525e763939 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -341,7 +341,8 @@ if __name__ == "__main__": num_blocks=int(num_blocks), block_size=args.block_size, name=args.name, - uuid=args.uuid)) + uuid=args.uuid, + optimal_io_boundary=args.optimal_io_boundary)) p = subparsers.add_parser('bdev_malloc_create', aliases=['construct_malloc_bdev'], help='Create a bdev with malloc backend') p.add_argument('-b', '--name', help="Name of the bdev") @@ -349,6 +350,8 @@ if __name__ == "__main__": p.add_argument( 'total_size', help='Size of malloc bdev in MB (float > 0)', type=float) p.add_argument('block_size', help='Block size for this bdev', type=int) + p.add_argument('-o', '--optimal-io-boundary', help="""Split on optimal IO boundary, in number of + blocks, default 0 (disabled)""", type=int) p.set_defaults(func=bdev_malloc_create) def bdev_malloc_delete(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 9e53ad68b3..b31f2f34c9 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -223,7 +223,7 @@ def bdev_ocf_set_cache_mode(client, name, mode): @deprecated_alias('construct_malloc_bdev') -def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None): +def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None, optimal_io_boundary=None): """Construct a malloc block device. Args: @@ -231,6 +231,7 @@ def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None): block_size: block size of device; must be a power of 2 and at least 512 name: name of block device (optional) uuid: UUID of block device (optional) + optimal_io_boundary: Split on optimal IO boundary, in number of blocks, default 0 (disabled, optional) Returns: Name of created block device. @@ -240,6 +241,8 @@ def bdev_malloc_create(client, num_blocks, block_size, name=None, uuid=None): params['name'] = name if uuid: params['uuid'] = uuid + if optimal_io_boundary: + params['optimal_io_boundary'] = optimal_io_boundary return client.call('bdev_malloc_create', params)