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 <mateusz.kozlowski@intel.com>
Change-Id: Ic0229e39109460f3541c31e1cbf2a485efe408c6
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460504
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Mateusz Kozlowski 2019-07-04 13:37:23 +02:00 committed by Jim Harris
parent 7a867c4fdb
commit cd115ecfcd
4 changed files with 97 additions and 12 deletions

View File

@ -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);

View File

@ -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

View File

@ -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):

View File

@ -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)