From cd115ecfcdd8291a886156114ad00b3fcaa8720e Mon Sep 17 00:00:00 2001 From: Mateusz Kozlowski Date: Thu, 4 Jul 2019 13:37:23 +0200 Subject: [PATCH] bdev/ftl: Add defrag parameters to construct_ftl_bdev rpc Added parsing and saving of (optional) parameters which are responsible for relocation in FTL. Changing the parameters may affect Write Amplification Factor and overall performance, especially during random write workloads. If parameters are not specified, default values will be used. Signed-off-by: Mateusz Kozlowski Change-Id: Ic0229e39109460f3541c31e1cbf2a485efe408c6 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460504 Reviewed-by: Konrad Sztyber Reviewed-by: Darek Stojaczyk Reviewed-by: Shuhei Matsumoto Tested-by: SPDK CI Jenkins --- lib/bdev/nvme/bdev_ftl.c | 12 ++++++++- lib/bdev/nvme/bdev_ftl_rpc.c | 52 ++++++++++++++++++++++++++++++++++++ scripts/rpc.py | 30 ++++++++++++++++++++- scripts/rpc/bdev.py | 15 ++++------- 4 files changed, 97 insertions(+), 12 deletions(-) diff --git a/lib/bdev/nvme/bdev_ftl.c b/lib/bdev/nvme/bdev_ftl.c index 7095c4e2f..7c3e76281 100644 --- a/lib/bdev/nvme/bdev_ftl.c +++ b/lib/bdev/nvme/bdev_ftl.c @@ -430,6 +430,7 @@ bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w { struct ftl_bdev *ftl_bdev = bdev->ctxt; struct spdk_ftl_attrs attrs; + struct spdk_ftl_conf *conf = &attrs.conf; char uuid[SPDK_UUID_STRING_LEN]; spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); @@ -441,7 +442,16 @@ bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w spdk_json_write_named_object_begin(w, "params"); spdk_json_write_named_string(w, "name", ftl_bdev->bdev.name); - spdk_json_write_named_bool(w, "allow_open_bands", attrs.conf.allow_open_bands); + spdk_json_write_named_bool(w, "allow_open_bands", conf->allow_open_bands); + spdk_json_write_named_uint64(w, "overprovisioning", conf->lba_rsvd); + spdk_json_write_named_uint64(w, "limit_crit", conf->limits[SPDK_FTL_LIMIT_CRIT].limit); + spdk_json_write_named_uint64(w, "limit_crit_threshold", conf->limits[SPDK_FTL_LIMIT_CRIT].thld); + spdk_json_write_named_uint64(w, "limit_high", conf->limits[SPDK_FTL_LIMIT_HIGH].limit); + spdk_json_write_named_uint64(w, "limit_high_threshold", conf->limits[SPDK_FTL_LIMIT_HIGH].thld); + spdk_json_write_named_uint64(w, "limit_low", conf->limits[SPDK_FTL_LIMIT_LOW].limit); + spdk_json_write_named_uint64(w, "limit_low_threshold", conf->limits[SPDK_FTL_LIMIT_LOW].thld); + spdk_json_write_named_uint64(w, "limit_start", conf->limits[SPDK_FTL_LIMIT_START].limit); + spdk_json_write_named_uint64(w, "limit_start_threshold", conf->limits[SPDK_FTL_LIMIT_START].thld); spdk_uuid_fmt_lower(uuid, sizeof(uuid), &attrs.uuid); spdk_json_write_named_string(w, "uuid", uuid); diff --git a/lib/bdev/nvme/bdev_ftl_rpc.c b/lib/bdev/nvme/bdev_ftl_rpc.c index 6d33a1932..946cf267d 100644 --- a/lib/bdev/nvme/bdev_ftl_rpc.c +++ b/lib/bdev/nvme/bdev_ftl_rpc.c @@ -71,6 +71,58 @@ static const struct spdk_json_object_decoder rpc_construct_ftl_decoders[] = { "allow_open_bands", offsetof(struct rpc_construct_ftl, ftl_conf) + offsetof(struct spdk_ftl_conf, allow_open_bands), spdk_json_decode_bool, true }, + { + "overprovisioning", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, lba_rsvd), spdk_json_decode_uint64, true + }, + { + "limit_crit", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) + + offsetof(struct spdk_ftl_limit, limit), + spdk_json_decode_uint64, true + }, + { + "limit_crit_threshold", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) + + offsetof(struct spdk_ftl_limit, thld), + spdk_json_decode_uint64, true + }, + { + "limit_high", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) + + offsetof(struct spdk_ftl_limit, limit), + spdk_json_decode_uint64, true + }, + { + "limit_high_threshold", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) + + offsetof(struct spdk_ftl_limit, thld), + spdk_json_decode_uint64, true + }, + { + "limit_low", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) + + offsetof(struct spdk_ftl_limit, limit), + spdk_json_decode_uint64, true + }, + { + "limit_low_threshold", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) + + offsetof(struct spdk_ftl_limit, thld), + spdk_json_decode_uint64, true + }, + { + "limit_start", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) + + offsetof(struct spdk_ftl_limit, limit), + spdk_json_decode_uint64, true + }, + { + "limit_start_threshold", offsetof(struct rpc_construct_ftl, ftl_conf) + + offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) + + offsetof(struct spdk_ftl_limit, thld), + spdk_json_decode_uint64, true + }, }; #define FTL_RANGE_MAX_LENGTH 32 diff --git a/scripts/rpc.py b/scripts/rpc.py index 367dcbe25..c36cb199c 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1299,7 +1299,24 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.set_defaults(func=destruct_split_vbdev) # ftl + ftl_valid_limits = ('crit', 'high', 'low', 'start') + def construct_ftl_bdev(args): + def parse_limits(limits, arg_dict, key_suffix=''): + for limit in limits.split(','): + key, value = limit.split(':', 1) + if key in ftl_valid_limits: + arg_dict['limit_' + key + key_suffix] = int(value) + else: + raise ValueError('Limit {} is not supported'.format(key)) + + arg_limits = {} + if args.limit_threshold: + parse_limits(args.limit_threshold, arg_limits, '_threshold') + + if args.limit: + parse_limits(args.limit, arg_limits) + print_dict(rpc.bdev.construct_ftl_bdev(args.client, name=args.name, trtype=args.trtype, @@ -1307,7 +1324,9 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse punits=args.punits, uuid=args.uuid, cache=args.cache, - allow_open_bands=args.allow_open_bands)) + allow_open_bands=args.allow_open_bands, + overprovisioning=args.overprovisioning, + **arg_limits)) p = subparsers.add_parser('construct_ftl_bdev', help='Add FTL bdev') @@ -1323,6 +1342,15 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' ' result in partial data recovery, instead of error', action='store_true') + p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed' + ' to user (optional)', type=int) + + limits = p.add_argument_group('Defrag limits', 'Configures defrag limits and thresholds for' + ' levels ' + str(ftl_valid_limits)[1:-1]) + limits.add_argument('--limit', help='Percentage of allowed user versus internal writes at given' + ' levels, e.g. crit:0,high:20,low:80') + limits.add_argument('--limit-threshold', help='Number of free bands triggering a given level of' + ' write limiting e.g. crit:1,high:2,low:3,start:4') p.set_defaults(func=construct_ftl_bdev) def delete_ftl_bdev(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 4c42e87b0..2a2c2bc15 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -596,7 +596,7 @@ def destruct_split_vbdev(client, base_bdev): return client.call('destruct_split_vbdev', params) -def construct_ftl_bdev(client, name, trtype, traddr, punits, allow_open_bands=None, uuid=None, cache=None): +def construct_ftl_bdev(client, name, trtype, traddr, punits, **kwargs): """Construct FTL bdev Args: @@ -604,20 +604,15 @@ def construct_ftl_bdev(client, name, trtype, traddr, punits, allow_open_bands=No trtype: transport type traddr: transport address punit: parallel unit range - uuid: UUID of the device - cache: name of the write buffer bdev - allow_open_bands: allow for partial restore after dirty shutdown + kwargs: optional parameters """ params = {'name': name, 'trtype': trtype, 'traddr': traddr, 'punits': punits} - if uuid: - params['uuid'] = uuid - if cache: - params['cache'] = cache - if allow_open_bands: - params['allow_open_bands'] = allow_open_bands + for key, value in kwargs.items(): + if value is not None: + params[key] = value return client.call('construct_ftl_bdev', params)