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)