diff --git a/Documentation/meson.build b/Documentation/meson.build index 65495e3cce..e81db8c902 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -32,6 +32,7 @@ adoc_sources = [ 'nvme-error-log', 'nvme-fdp-configs', 'nvme-fdp-events', + 'nvme-fdp-feature', 'nvme-fdp-set-events', 'nvme-fdp-stats', 'nvme-fdp-status', diff --git a/Documentation/nvme-fdp-feature.txt b/Documentation/nvme-fdp-feature.txt new file mode 100644 index 0000000000..543c7883f2 --- /dev/null +++ b/Documentation/nvme-fdp-feature.txt @@ -0,0 +1,56 @@ +nvme-fdp-feature(1) +=================== + +NAME +---- +nvme-fdp-feature - Show or change Flexible Data Placement (FDP) Feature + +SYNOPSIS +-------- +[verse] +'nvme fdp' [--endgrp-id= | -e ] + [--enable-conf-idx= | -c ] + [--disable | -d] + [--verbose | -v] + +DESCRIPTION +----------- +For the NVMe device given, configure and manage the Flexible Data Placement (FDP) feature. + +This command can be used to either show the current FDP feature configuration or change it. + + If no `--enable-conf-idx` or `--disable` options are provided, the current configuration is +displayed. + +If the `--enable-conf-idx` or `--disable` options are provided, configuration is changed +accordingly. Device may refuse the change if there is a namespace. + +The parameter is mandatory and must be a NVMe character device (ex: /dev/nvme0) + +OPTIONS +------- +-e :: +--endgrp-id=:: + Specify the endurance group ID. This option is mandatory if device supports endurance groups. + +-c :: +--enable-conf-idx=:: + Enable FDP feature with the specified configuration. The configuration index matches position + listed by nvme-fdp-config(1). + +-d:: +--disable:: + Disable the current FDP feature configuration. + +-v:: +--verbose:: + Increase verbosity of the output. + +SEE ALSO +-------- +nvme-list-endgrp(1) +nvme-fdp-config(1) + +NVME +---- +Part of nvme-cli \ No newline at end of file diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c index c61706ac47..1aec7579d6 100644 --- a/plugins/fdp/fdp.c +++ b/plugins/fdp/fdp.c @@ -551,3 +551,99 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu return err; } + +static int fdp_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Show, enable or disable FDP configuration"; + const char *enable_conf_idx = "FDP configuration index to enable"; + const char *endurance_group = "Endurance group ID"; + const char *disable = "Disable current FDP configuration"; + + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + int err = -1; + __u32 result; + bool enabling_conf_idx = false; + struct nvme_set_features_args setf_args = { + .args_size = sizeof(setf_args), + .fd = -1, + .fid = NVME_FEAT_FID_FDP, + .save = 1, + .nsid = NVME_NSID_ALL, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + + struct config { + bool disable; + __u8 fdpcidx; + __u16 endgid; + }; + + struct config cfg = { + .disable = false, + .fdpcidx = 0, + .endgid = 0, + }; + + OPT_ARGS(opts) = { + OPT_SHRT("endgrp-id", 'e', &cfg.endgid, endurance_group), + OPT_BYTE("enable-conf-idx", 'c', &cfg.fdpcidx, enable_conf_idx), + OPT_FLAG("disable", 'd', &cfg.disable, disable), + OPT_INCR("verbose", 'v', &nvme_cfg.verbose, verbose), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + enabling_conf_idx = argconfig_parse_seen(opts, "enable-conf-idx"); + if (enabling_conf_idx && cfg.disable) { + nvme_show_error("Cannot enable and disable at the same time"); + return -EINVAL; + } + + if (!enabling_conf_idx && !cfg.disable) { + struct nvme_get_features_args getf_args = { + .args_size = sizeof(getf_args), + .fd = dev_fd(dev), + .fid = NVME_FEAT_FID_FDP, + .nsid = NVME_NSID_ALL, + .sel = NVME_GET_FEATURES_SEL_CURRENT, + .cdw11 = cfg.endgid, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + nvme_show_result("Endurance Group : %d", cfg.endgid); + + err = nvme_get_features(&getf_args); + if (err) { + nvme_show_status(err); + return err; + } + + nvme_show_result("Flexible Direct Placement Enable (FDPE) : %s", + (result & 0x1) ? "Yes" : "No"); + nvme_show_result("Flexible Direct Placement Configuration Index : %u", + (result >> 8) & 0xf); + return err; + } + + setf_args.fd = dev_fd(dev); + setf_args.cdw11 = cfg.endgid; + setf_args.cdw12 = cfg.fdpcidx << 8 | (!cfg.disable); + + err = nvme_set_features(&setf_args); + if (err) { + nvme_show_status(err); + return err; + } + nvme_show_result("Success %s Endurance Group: %d, FDP configuration index: %d", + (cfg.disable) ? "disabling" : "enabling", cfg.endgid, cfg.fdpcidx); + return err; +} diff --git a/plugins/fdp/fdp.h b/plugins/fdp/fdp.h index f162b32116..0cd44fb43f 100644 --- a/plugins/fdp/fdp.h +++ b/plugins/fdp/fdp.h @@ -15,7 +15,8 @@ PLUGIN(NAME("fdp", "Manage Flexible Data Placement enabled devices", NVME_VERSIO ENTRY("events", "List events affecting reclaim units and media usage", fdp_events) ENTRY("status", "Show reclaim unit handle status", fdp_status) ENTRY("update", "Update a reclaim unit handle", fdp_update) - ENTRY("set-events", "Enabled or disable events", fdp_set_events) + ENTRY("set-events", "Enable or disable events", fdp_set_events) + ENTRY("feature", "Show, enable or disable FDP configuration", fdp_feature) ) );